Win32Api USB SetupDiGetDeviceInterfaceDetail失败

我正在尝试连接USB GPS设备。 如果我通过CreateFile WinApi手动创建文件(使用设备管理器中指定的路径),我可以成功连接到设备。

但是,当我尝试通过枚举选择设备时,我失败了@ SetupDiGetDeviceInterfaceDetail调用。

我有正确的C代码,但我的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#

 [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 

恭喜,它正在运作。 你会得到一个Unicode字符串,它的长度是你的两倍。 并且FALSE返回是正确的。 您只需要调用Marshal.GetLastWin32Error()并validation您是否获得了ERROR_INSUFFICIENT_BUFFER。 你的C代码坏了,可能是因为你忘了将theBytesReturned初始化为零。

我相信我发现了问题。

在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