2016-09-20 76 views
2

信息:ç句柄#獲取列表,AcessViolationException

  • .NET 4.5

測試上:

  • 的Win7 64位

  • Win10 64位(虛擬盒)

我想獲得一個外部進程句柄的列表,並返回他們的名字作爲字符串,所以我可以關閉一個特定的一個之後。 `

 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; 
     }` 

問題不過是,這個代碼工作在Win7 64位,而不是在Win10:因此,我使用這將檢查的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位模式的Buffer-field之前有4個填充字節。 我workaraound是這樣的:

[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; 
} 

在我的研究,我發現關於這個話題,基本上有兩種示例代碼 已經複製在互聯網上,我正在考慮創建一個開源的這麼多問題名爲WinKernelObjectsDotNet的庫。

更新:圖書館現在可用here。它支持使用一行代碼來查找鎖定文件或串行端口(COM)的進程。