2010-09-21 176 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

相關問題