2016-09-20 74 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)的进程。