2012-02-12 124 views
2

我正在嘗試連接到USB GPS設備。如果我通過CreateFile WinApi手動創建文件(使用設備管理器中指定的路徑),我可以成功連接到設備。Win32Api USB SetupDiGetDeviceInterfaceDetail失敗

但是,當我嘗試通過枚舉選擇設備時,失敗@ SetupDiGetDeviceInterfaceDetail調用。

我有正確工作的C代碼,但我的C#翻譯似乎無法正常工作。我嘗試了許多基本相同的結果。

的作品

// Get enumerator handle for the specified ClassGuid 
HDEVINFO theDevInfo = SetupDiGetClassDevs((GUID*)&GUID_DEVINTERFACE_GRMNUSB, NULL, NULL, 
    DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); 

SP_DEVICE_INTERFACE_DATA theInterfaceData; 
theInterfaceData.cbSize = sizeof(theInterfaceData); 

// populate theInterfaceData which contains device class information 
if (!SetupDiEnumDeviceInterfaces(theDevInfo, NULL, (GUID*)&GUID_DEVINTERFACE_GRMNUSB, 0, &theInterfaceData) && 
    GetLastError() == ERROR_NO_MORE_ITEMS) 
{ 
    gHandle = 0; 
    return; 
} 
// This is normally used to obtain the device path information using theInterfaceData obtained above 
bool initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, &theInterfaceData, NULL, 0, &theBytesReturned, NULL); 
// theBytesReturned = 83 
theDevDetailData = 
(PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(theBytesReturned); 
theDevDetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 

bool initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, &theInterfaceData, theDevDetailData, theBytesReturned, NULL, &theDevInfoData); 

C代碼C#

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern Boolean SetupDiGetDeviceInterfaceDetail(
    IntPtr hDevInfo, 
    ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, 
    IntPtr deviceInterfaceDetailData, 
    UInt32 deviceInterfaceDetailDataSize, 
    out UInt32 requiredSize, 
    IntPtr deviceInfoData 
    ); 

[StructLayout(LayoutKind.Sequential)] 
public struct SP_DEVICE_INTERFACE_DATA 
{ 
    public Int32 cbSize; 
    public Guid interfaceClassGuid; 
    public Int32 flags; 
    private UIntPtr reserved; 
} 


// Get enumerator handle for the specified ClassGuid 
IntPtr theDevInfo = SetupDiGetClassDevs(ref ClassGuid, (DiGetClassFlags.DIGCF_PRESENT | DiGetClassFlags.DIGCF_DEVICEINTERFACE)); 

SP_DEVICE_INTERFACE_DATA DevInterfaceData = new SP_DEVICE_INTERFACE_DATA(); 
DevInterfaceData.cbSize = Marshal.SizeOf(DevInterfaceData); 

initialized = SetupDiEnumDeviceInterfaces(theDevInfo, IntPtr.Zero, ref ClassGuid, 0, 
     ref DevInterfaceData); 
// I assume The DevInterfaceData is populated correctly as it matches the C Code 
// And I've compared the values in memory and they match 

uint bytesReturned = 0; 
initialized = SetupDiGetDeviceInterfaceDetail(theDevInfo, ref DevInterfaceData, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); 
// I expect bytesReturned = 83 and initialized = true which is the value that is returned in the C Code 
// Instead the value 162 is returned 

回答

2

我相信我發現這個問題。

各地pinvoke.net戳後,我發現下面

// build a Device Interface Detail Data structure 
SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA(); 
if (IntPtr.Size == 8) // for 64 bit operating systems 
    didd.cbSize = 8; 
else didd.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit systems 

在我的代碼更改,這允許我適當地獲得則DevicePath。

有興趣的人蔘考。

http://pinvoke.net/default.aspx/setupapi.SetupDiGetDeviceInterfaceDetail

+1

不,這會破壞堆棧。使用Marshal.AllocHGlobal()來分配具有所需大小的緩衝區。你從第一個電話獲得的大小。 – 2012-02-12 08:25:38

+0

爲什麼/如何損壞堆棧?當我進行Win32api調用時,是不是應該封送適當的內存? – galford13x 2012-02-12 09:43:46

+0

@HansPassant你有可能解釋爲什麼'IntPtr.Size'測試是必要的,我們不能依靠編組器來獲得'SizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA)'對嗎?我猜它與填充有關嗎? – 2014-06-21 17:25:59

4

恭喜,它正在工作。你會得到一個Unicode字符串,它的長度是它的兩倍。並且FALSE返回是正確的。你只需要調用Marshal.GetLastWin32Error()並確認你得到了ERROR_INSUFFICIENT_BUFFER。你的C代碼被破壞了,可能是因爲你忘記初始化返回爲零的字節。

+0

C代碼正常工作。這是C#代碼無法正常工作。 theBytesReturned被初始化爲0,它只是沒有顯示在上面的代碼,因爲我沒有把整個功能來節省空間。我猜C代碼由於是ASCII而返回了83個字節,但是如果C#代碼需要一個UNICODE字符串,爲什麼它是162而不是83x2 = 166? – galford13x 2012-02-12 08:55:39

+0

我不知道,發佈字符串,我會告訴你爲什麼。 C代碼確實存在問題,函數必須返回FALSE,並且GetLastError()必須返回ERROR_INSUFFICIENT_BUFFER。然後您知道所需的緩衝區大小,分配它並再次調用該函數。 – 2012-02-12 09:15:10

+0

哦,是的,我同意,第一次調用返回false,還有第二次調用,我顯然沒有把這是實際deviceDetailData讀取。我會編輯我的帖子以保持正確。這裏是字符串@「\\?\ usb#vid_091e&pid_0003#5&4a03a84&0&5#{2c9c45c2-8e7d-4c08-a12d-816bbae722c0}」 – galford13x 2012-02-12 09:37:27

相關問題