Win32Api USB SetupDiGetDeviceInterfaceDetail échoue

Je tente de me connecter à un périphérique GPS USB. Je peux réussir à me connecter au périphérique si je crée manuellement un fichier via CreateFile WinApi (en utilisant le chemin spécifié dans le Gestionnaire de périphériques).

Cependant, lorsque j’essaie de sélectionner le périphérique par énumération, j’échoue @ de l’appel SetupDiGetDeviceInterfaceDetail.

J’ai un code C qui fonctionne correctement, mais ma traduction C # ne semble pas fonctionner correctement. J’ai essayé de nombreuses variantes avec essentiellement les mêmes résultats.

C code qui fonctionne

// 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 

Félicitations, ça marche. Vous obtiendrez une chaîne Unicode, elle est deux fois plus longue. Et un faux retour est correct. Il vous suffit d’appeler Marshal.GetLastWin32Error () et de vérifier que vous avez bien ERROR_INSUFFICIENT_BUFFER. Votre code C est cassé, probablement parce que vous avez oublié d’initialiser theBytesReturned à zéro.

Je crois avoir trouvé le problème.

Après avoir fouillé pinvoke.net, j’ai trouvé ce qui suit

 // 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 

Changer cela dans mon code me permet d’obtenir le DevicePath correctement.

Référence pour les intéressés.

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