Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 32位与64位版本类型的条件编译的首选方法_C#_.net_Interop_Pinvoke_Marshalling - Fatal编程技术网

C# 32位与64位版本类型的条件编译的首选方法

C# 32位与64位版本类型的条件编译的首选方法,c#,.net,interop,pinvoke,marshalling,C#,.net,Interop,Pinvoke,Marshalling,某个任务需要我枚举系统中的所有句柄。到目前为止,我发现最好的方法是使用文档不足的SystemHandleInformation标志作为class参数 到目前为止还不错。但是,在64位Windows上以32位模式运行时,所需的结构如下: // 32-bit version [StructLayout(LayoutKind.Sequential, Pack=1)] public struct SYSTEM_HANDLE_INFORMATION { public uint ProcessID;

某个任务需要我枚举系统中的所有句柄。到目前为止,我发现最好的方法是使用文档不足的
SystemHandleInformation
标志作为class参数

到目前为止还不错。但是,在64位Windows上以32位模式运行时,所需的结构如下:

// 32-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public uint ProcessID;               
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public uint Object_Pointer;       
    public UInt32 GrantedAccess;        
}
// 64-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public int Reserved;            // unknown, no documentation found
    public uint ProcessID;               
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public long Object_Pointer;       
    public UInt32 GrantedAccess;        
}
对于64位Windows(x64,我没有测试安腾,我希望不会有什么不同…),其结构如下:

// 32-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public uint ProcessID;               
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public uint Object_Pointer;       
    public UInt32 GrantedAccess;        
}
// 64-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public int Reserved;            // unknown, no documentation found
    public uint ProcessID;               
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public long Object_Pointer;       
    public UInt32 GrantedAccess;        
}
现在,我应该将
Object\u指针
更改为
IntPtr
。我曾一度希望我能用
ProcessId
做同样的事情,有一篇参考文章说这实际上是一个
句柄,实际上是一个64位的值。但是,
Reserved
始终为零,因此我无法以相同的方式将其合并到
IntPtr

这可能不是发生这种情况的唯一情况。我正在寻找处理此类差异的最佳实践方法:

  • 除非我想维护单独的二进制文件,否则在这里使用像WIN32(在IntPtr的参考源代码中内部使用)那样的常量是行不通的
  • 如果IntPtr.Size==4,我可以编写两个不同的函数和两个不同的结构,创建一个包装器并在代码中使用
    。这适用于外部函数,但不适用于类型
  • 我可以重载
    GetType
    ,但我不确定这会导致什么(可能有助于编组?)
  • 还有别的吗

所有这些似乎都不理想,但到目前为止,唯一简单的方法似乎是使用
if IsWin64()
语句提升我的系统。我希望听到比我更好的方法。

鉴于IntPtr的大小不同,为什么不尝试以下方法:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
    public IntPtr ProcessID;               // mask with 0xffffffff
    public byte ObjectTypeNumber;       
    public byte Flags;                  
    public ushort Handle;               
    public IntPtr Object_Pointer;          // again good for 32/64bit
    public UInt32 GrantedAccess;        
}

这应该适用于32位和64位不变的情况。

就是这样-SystemHandleInformation的结构只提供16位PID。您可以在XP及更高版本上使用SystemExtendedHandle信息

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public class SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
  {
    public IntPtr Object;
    public IntPtr UniqueProcessId;
    public IntPtr HandleValue;
    public uint GrantedAccess;
    public ushort CreatorBackTraceIndex;
    public ushort ObjectTypeIndex;
    public uint HandleAttributes;
    public uint Reserved;
  }

  internal enum SYSTEM_INFORMATION_CLASS
  {
    SystemBasicInformation = 0,
    SystemPerformanceInformation = 2,
    SystemTimeOfDayInformation = 3,
    SystemProcessInformation = 5,
    SystemProcessorPerformanceInformation = 8,
    SystemHandleInformation = 16,
    SystemInterruptInformation = 23,
    SystemExceptionInformation = 33,
    SystemRegistryQuotaInformation = 37,
    SystemLookasideInformation = 45,
    SystemExtendedHandleInformation = 64,
  }


 [DllImport("ntdll.dll", CharSet=CharSet.Auto)]
 private static extern int NtQuerySystemInformation(int InfoType, IntPtr lpStructure, int StructSize, out int returnLength);



  public static void Main(string[] args)
  {
    Console.WriteLine(Environment.Is64BitProcess ? "x64" : "x32");
    Console.WriteLine();

    var infoSize = Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));

    Console.WriteLine("sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): {0}", infoSize);
    int allSize = 1000 * infoSize;
    var buffer = Marshal.AllocHGlobal(allSize);
    var status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize);
    Console.WriteLine("status: {0:x}, return len: {1}", status, allSize);

    if (status != 0)
    {
      allSize += 40 * infoSize;
      Marshal.FreeHGlobal(buffer);
      buffer = Marshal.AllocHGlobal(allSize);
      status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize);
      Console.WriteLine("status: {0:x}, return len: {1}", status, allSize);
    }

    Console.WriteLine();
    var info = new SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX();
    //for (var i = 0; i < allSize; i += infoSize)
    for (var i = 0; i < Math.Min(allSize, 20 * infoSize); i+= infoSize) // for testing purpose only 20
    {
      Marshal.PtrToStructure(IntPtr.Add(buffer, i), info);
      Console.WriteLine("{0,16:x}, {1,16:x}, {2,16:x}, {3,6:x}, {4,8:x}", info.Object.ToInt64(), info.UniqueProcessId.ToInt64(), info.HandleValue.ToInt64(), info.GrantedAccess, info.HandleAttributes);
    }
    Marshal.FreeHGlobal(buffer);
  }

这类代码就像青少年性行为,一个错误,你将支持它到你的余生。使用Process类来运行SysInternals的Handle.exe实用程序,至少您可以让其他人支持它。@HansPassant:LOL!是的,我已经考虑过使用SysInternal的任何实用程序,但是没有,不适合我的场景。谢谢你的指针。是的,我试了几次,但是它产生了错误的ProcessID。也许这是一个好主意,然后我应该用一个方法
GetProcessId()
来展开这个结构,该方法进行解蔽并将ProcessID标记为private。@Abel:在64位中,只需右移32位即可。我不确定endian的问题:)它从字节序列
00 00 04 00
获取进程ID 4(系统)作为
0x000000040000000
,即
17179869184
。因此,是的,endianness是一个问题(在这个意义上,前导保留零是一个障碍)<代码>0x000000040000000>>32
可以在64位的情况下工作。这非常好。我问的是一种处理咬人问题的更好方法,但我更具体的问题得到了答案。我不知道扩展版,谢谢!