结构大小,检查是64位还是32位
我有一个Windows应用程序执行一个简单的例程来确定是否存在USB令牌。该方法在32位机器上始终正常工作,但在64位机器上进行测试时,我们开始发现意外的结果。结构大小,检查是64位还是32位
我打电话以下方法
[StructLayout(LayoutKind.Sequential)]
internal struct SP_DEVINFO_DATA
{
public Int32 cbSize;
public Guid ClassGuid;
public Int32 DevInst;
public UIntPtr Reserved;
};
[DllImport("setupapi.dll")]
internal static extern Int32 SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, Int32 MemberIndex, ref SP_DEVINFO_DATA DeviceInterfaceData);
的说明文件SP_DEVINFO_DATA结构告诉我们,CBSIZE是 大小,以字节为单位SP_DEVINFO_DATA结构。
如果我们计算CBSIZE对于一个32位的机这将是一个64位的机28和32。
我已经用不同的CBSIZE值重新编译测试这两台机器,我想知道的是如何计算这个作为运行?我的应用程序需要在两种架构上运行。
internal static Int32 GetDeviceInfoData(Int32 iMemberIndex)
{
_deviceInfoData = new Win32DeviceMgmt.SP_DEVINFO_DATA
{
cbSize = ?? // 28 When 32-Bit, 32 When 64-Bit,
ClassGuid = Guid.Empty,
DevInst = 0,
Reserved = UIntPtr.Zero
};
return Win32DeviceMgmt.SetupDiEnumDeviceInfo(_deviceInfoSet, iMemberIndex, ref _deviceInfoData);
}
感谢
罗汉
使用Marshal.SizeOf:
_deviceInfoData = new Win32DeviceMgmt.SP_DEVINFO_DATA
{
cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(Win32DeviceMgmt.SP_DEVINFO_DATA);
// etc..
}
看起来像一个对齐问题。
尝试将Pack财产。
编辑
我看着它:http://www.pinvoke.net/default.aspx/Structures/SP_DEVINFO_DATA.html
它说:
在32位平台上,所有SETUPAPI 结构为1字节的包装。在64位 平台上,SetupApi结构为 8字节打包。 IE用于32位 SP_DEVINFO_DATA.cbSize = 28,对于64位 SP_DEVINFO_DATA.cbSize =(28 + 4)= 32.SP_DEVINFO_DATA.cbSize =(28 + 4)= 32。
我已经试过这个属性,但它没有工作。如果您查看SP_DEVINFO_DATA结构的文档,则必须将cbSize指定为结构的大小。 – 2010-09-21 01:30:52
的32 IntPtr
变化和64 大小尝试
cbsize = IntPtr.Size == 4 ? 28 : 32
编辑:修正为IntPtr.Size,但我喜欢汉斯System.Runtime.InteropServices.Marshal.SizeOf(typeof(Win32DeviceMgmt.SP_DEVINFO_DATA);
因为没有幻数较好。不知道那是在那里。
你好,我意识到IntPtr的大小发生了变化,你认为这种方法是最佳实践吗? – 2010-09-21 01:32:51
其IntPtr.Size – 2010-09-21 01:33:54
为什么不Environment.Is64BitOperatingSystem
或Environment.Is64BitProcess
。
与“IntPtr.Size”不同,当我们有128位和256位进程时,这些将会中断。 – 2010-09-21 12:02:39
@Steven:当时我们将拥有'Environment.Is128BitOperatingSystem'或甚至'int Environment.GetOSBits()'。 – 2010-09-21 12:51:00
是的,代码不知道调用这些,所以它会中断。另一方面,如果它调用“IntPtr.Size”并使用该值,则不会中断。 – 2010-09-21 16:51:36
汉斯,这解决了如何通过实际大小的问题,所以我upvoting。不过,我仍然有点关心包装。没有意义的时候通过实际的大小。 – 2010-09-21 16:56:48
@Steven - 如果包装不正确,那么将cbSize设置为一个常量值实际上是一件非常糟糕的事情。它不会让API检测到你错了,并报告一个很好的错误。它会随机失败,因为它会读取垃圾。 – 2010-09-21 17:25:48
@Hans - 欢呼声,效果很棒! – 2010-09-21 19:46:08