2016-09-20 3 views
2

정보 :C 핸들 #의 가져 오기 목록, AcessViolationException

  • Win7에 64 비트

  • Win10 64 비트 (가상 :

    • 닷넷 4.5

    는에서 테스트 박스)

외부 프로세스의 핸들 목록을 가져 와서 해당 이름을 문자열로 반환하려고 시도하고 있으므로 나중에 특정 프로세스를 닫을 수 있습니다. `

 const int CNST_SYSTEM_HANDLE_INFORMATION = 16; 
     const uint STATUS_INFO_LENGTH_MISMATCH = 0xc0000004; 

     public static string getObjectTypeName(Win32API.SYSTEM_HANDLE_INFORMATION shHandle, Process process) 
     { 
      IntPtr m_ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id); 
      IntPtr ipHandle = IntPtr.Zero; 
      var objBasic = new Win32API.OBJECT_BASIC_INFORMATION(); 
      IntPtr ipBasic = IntPtr.Zero; 
      var objObjectType = new Win32API.OBJECT_TYPE_INFORMATION(); 
      IntPtr ipObjectType = IntPtr.Zero; 
      IntPtr ipObjectName = IntPtr.Zero; 
      string strObjectTypeName = ""; 
      int nLength = 0; 
      int nReturn = 0; 
      IntPtr ipTemp = IntPtr.Zero; 


      if (!Win32API.DuplicateHandle(m_ipProcessHwnd, shHandle.Handle, 
              Win32API.GetCurrentProcess(), out ipHandle, 
              0, false, Win32API.DUPLICATE_SAME_ACCESS)) 
       return null; 



      ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic)); 
      Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation, 
            ipBasic, Marshal.SizeOf(objBasic), ref nLength); 
      objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType()); 
      Marshal.FreeHGlobal(ipBasic); 

      ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength); 
      nLength = objBasic.TypeInformationLength; 
      while ((uint)(nReturn = Win32API.NtQueryObject(
       ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType, 
        nLength, ref nLength)) == 
       Win32API.STATUS_INFO_LENGTH_MISMATCH) 
      { 
       Marshal.FreeHGlobal(ipObjectType); 
       ipObjectType = Marshal.AllocHGlobal(nLength); 
      } 

      objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType()); 
      if (Is64Bits()) 
      { 
       ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32); 
      } 
      else 
      { 
       ipTemp = objObjectType.Name.Buffer; 
      } 

     strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1); 


     Marshal.FreeHGlobal(ipObjectType); 
      Win32API.CloseHandle(ipHandle); 
      return strObjectTypeName; 
     }` 

이 문제 그러나이 코드는하지 Win10에서, Win7에 64 비트에서 작동한다는 것입니다 : 그러므로 나는 핸들이 내가 닫으려는 핸들 있는지 확인합니다 Win32API를 사용하여이 기능을 썼다! -> 승리 10에서 strObjectTypeName = Marshal.PtrToStringUni();AcessViolationException (코드에서 마지막 몇 줄) 보호 된 메모리를 읽거나 쓰려고 시도

System.AccessViolationException가 발생합니다. 이것은 종종 다른 메모리가 손상되었다는 표시입니다.

win10에서 관리되지 않는 메모리에 액세스하는 방법에 대한 내용이 여기에 누락 되었습니까?

답변

0

나는 같은 문제에 직면했다. 나는 Win7을 시도하지 않았지만 Win10 (x64)의 코드를 32 비트로 실행하면 (예 : 응용 프로그램의 "32 비트 플래그 선호"설정) 작동해야합니다. 예외가 발생하면 & 변수를 "ipTemp"변수를 Visual Studio의 "메모리 창"으로 끌어 놓습니다. 물음표 만 표시되거나 유효한 포인터가없는 오류 메시지 만 표시되는 경우 내가 알아 낸 한,이 API에서 사용하는 구조체의 64 비트 버전에는 (더 많은) 패딩 바이트가 있습니다. OBJECT_TYPE_INFORMATION에는 UNICODE_STRING이 있고 UNICODE_STRING에는 64 비트 모드의 버퍼 필드 앞에 4 개의 패딩 바이트가 있습니다. 나는이 주제에 내가 오픈 소스를 만들 고려하고 모든 인터넷을 통해 복사 된 샘플 코드 의 기본적 이가지에 관한 많은 질문을 찾아 내 연구하는 동안

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct UNICODE_STRING 
{ 
    private IntPtr _dummy; // the two ushorts seem to be padded with 4 bytes in 64bit mode only 

    /// <summary> 
    /// The length, in bytes, of the string stored in Buffer. If the string is null-terminated, Length does not include the trailing null character. 
    /// </summary> 
    public ushort Length 
    { 
     get { return (ushort)Marshal.ReadInt16(this, 0); } 
    } 

    /// <summary> 
    /// The length, in bytes, of Buffer. 
    /// </summary> 
    public ushort MaximumLength 
    { 
     get { return (ushort)Marshal.ReadInt16(this, 2); } 
    } 

    public IntPtr Buffer; 
} 

: 내 workaraound이이었다 WinKernelObjectsDotNet이라는 라이브러리

업데이트 : 라이브러리는 현재 here입니다. 한 줄의 코드로 파일이나 직렬 포트 (COM)를 잠그는 프로세스를 찾는 것을 지원합니다.