2010-09-21 110 views
3

我有一个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); 
} 

感谢

罗汉

回答

9

使用Marshal.SizeOf:

_deviceInfoData = new Win32DeviceMgmt.SP_DEVINFO_DATA 
    { 
     cbSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(Win32DeviceMgmt.SP_DEVINFO_DATA); 
     // etc.. 
    } 
+0

汉斯,这解决了如何通过实际大小的问题,所以我upvoting。不过,我仍然有点关心包装。没有意义的时候通过实际的大小。 – 2010-09-21 16:56:48

+1

@Steven - 如果包装不正确,那么将cbSize设置为一个常量值实际上是一件非常糟糕的事情。它不会让API检测到你错了,并报告一个很好的错误。它会随机失败,因为它会读取垃圾。 – 2010-09-21 17:25:48

+0

@Hans - 欢呼声,效果很棒! – 2010-09-21 19:46:08

0

看起来像一个对齐问题。

尝试将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。

+0

我已经试过这个属性,但它没有工作。如果您查看SP_DEVINFO_DATA结构的文档,则必须将cbSize指定为结构的大小。 – 2010-09-21 01:30:52

1

的32 IntPtr变化和64 大小尝试

cbsize = IntPtr.Size == 4 ? 28 : 32 

编辑:修正为IntPtr.Size,但我喜欢汉斯System.Runtime.InteropServices.Marshal.SizeOf(typeof(Win32DeviceMgmt.SP_DEVINFO_DATA);因为没有幻数较好。不知道那是在那里。

+0

你好,我意识到IntPtr的大小发生了变化,你认为这种方法是最佳实践吗? – 2010-09-21 01:32:51

+0

其IntPtr.Size – 2010-09-21 01:33:54

1

为什么不Environment.Is64BitOperatingSystemEnvironment.Is64BitProcess

+0

与“IntPtr.Size”不同,当我们有128位和256位进程时,这些将会中断。 – 2010-09-21 12:02:39

+1

@Steven:当时我们将拥有'Environment.Is128BitOperatingSystem'或甚至'int Environment.GetOSBits()'。 – 2010-09-21 12:51:00

+0

是的,代码不知道调用这些,所以它会中断。另一方面,如果它调用“IntPtr.Size”并使用该值,则不会中断。 – 2010-09-21 16:51:36

相关问题