【问题标题】:Retrieve 'Device Instance Path' from attached USB device从连接的 USB 设备中检索“设备实例路径”
【发布时间】:2015-11-20 17:50:19
【问题描述】:

我关注了一些资源,包括 this 一个资源,我可以在其中检索 USB 设备的 pid、vid 等属性,但我需要检索“设备实例路径”,因为它包含序列号(最后 4数字),这最终是我想要的。

我尝试使用来自here 的代码来检索序列号,但它适用于 USB 存储设备,我的是一个独立设备,它具有类似于相机的 USB 连接。

QString USBDevices::findDevice()
{
    GUID*pClassGuid = NULL;
    LPCTSTR pszEnumerator = TEXT("USB");

    unsigned i, j;
    DWORD dwSize, dwPropertyRegDataType;
    DEVPROPTYPE ulPropertyType;
    CONFIGRET status;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    const static LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};
    TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
    TCHAR szDesc[1024], szHardwareIDs[4096];
    WCHAR szBuffer[4096];
    LPTSTR pszToken, pszNextToken;
    TCHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];
    FN_SetupDiGetDevicePropertyW fn_SetupDiGetDevicePropertyW = (FN_SetupDiGetDevicePropertyW)
        GetProcAddress (GetModuleHandle (TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");

    // List all connected USB devices
    hDevInfo = SetupDiGetClassDevs (pClassGuid, pszEnumerator, NULL,
                                    pClassGuid != NULL ? DIGCF_PRESENT: DIGCF_ALLCLASSES | DIGCF_PRESENT);


    //hDevInfo = SetupDiGetClassDevs(NULL,0,0, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);

    if (hDevInfo == INVALID_HANDLE_VALUE)
        return "";

    // Find the ones that are driverless
    for (i = 0; ; i++)  {
        DeviceInfoData.cbSize = sizeof (DeviceInfoData);
        if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
            break;

        status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0);
        if (status != CR_SUCCESS)
            continue;

        // Display device instance ID
        qDebug() << QString::fromWCharArray(szDeviceInstanceID);

        if (SetupDiGetDeviceRegistryProperty (hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
                                              &dwPropertyRegDataType, (BYTE*)szDesc,
                                              sizeof(szDesc),   // The size, in bytes
                                              &dwSize))
            qDebug() << "    Device Description: " << QString::fromWCharArray(szDesc);

        if (SetupDiGetDeviceRegistryProperty (hDevInfo, &DeviceInfoData, SPDRP_HARDWAREID,
                                              &dwPropertyRegDataType, (BYTE*)szHardwareIDs,
                                              sizeof(szHardwareIDs),    // The size, in bytes
                                              &dwSize)) {
            LPCTSTR pszId;
            qDebug() << "    Hardware IDs:\n";
            for (pszId=szHardwareIDs;
                 *pszId != TEXT('\0') && pszId + dwSize/sizeof(TCHAR) <= szHardwareIDs + ARRAYSIZE(szHardwareIDs);
                 pszId += lstrlen(pszId)+1) {

                qDebug() << QString::fromWCharArray(pszId);
            }
        }

        // Retreive the device description as reported by the device itself
        // On Vista and earlier, we can use only SPDRP_DEVICEDESC
        // On Windows 7, the information we want ("Bus reported device description") is
        // accessed through DEVPKEY_Device_BusReportedDeviceDesc
        if (fn_SetupDiGetDevicePropertyW && fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
                                                                          &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {

            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0))
            {
                QString busReportedDeviceDescription = QString::fromWCharArray(szBuffer);
                qDebug() << "    Bus Reported Device Description: " << QString::fromWCharArray(szBuffer);

                if ( busReportedDeviceDescription == MY_DEVICE )
                {
                    qDebug() << getSerialNum( hDevInfo );
                    return busReportedDeviceDescription;
                }
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_Manufacturer,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {
                qDebug() << "    Device Manufacturer: " << QString::fromWCharArray(szBuffer);
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_FriendlyName,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {
                qDebug() << "    Device Friendly Name: " <<  QString::fromWCharArray(szBuffer);
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_LocationInfo,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {
                qDebug() << "    Device Location Info: " << QString::fromWCharArray(szBuffer);
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_SecuritySDS,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {
                // See Security Descriptor Definition Language on MSDN
                // (http://msdn.microsoft.com/en-us/library/windows/desktop/aa379567(v=vs.85).aspx)
                qDebug() << "    Device Security Descriptor String: " << QString::fromWCharArray(szBuffer);
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_ContainerId,
                                              &ulPropertyType, (BYTE*)szDesc, sizeof(szDesc), &dwSize, 0)) {
                StringFromGUID2((REFGUID)szDesc, szBuffer, ARRAY_SIZE(szBuffer));
                qDebug() << "    ContainerId: " << QString::fromWCharArray(szBuffer);
            }
            if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_DeviceDisplay_Category,
                                              &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0))
                qDebug() << "    Device Display Category: " << QString::fromWCharArray(szBuffer);
        }

        QString deviceInstanceID( QString::fromWCharArray( szDeviceInstanceID ) );
        QRegExp splitBy("(\\\\|\\&|\\#)");
        QStringList deviceInstanceIDItems = deviceInstanceID.split(splitBy);

        QString vid;
        QString pid;
        QString mi;

        if (deviceInstanceIDItems.count() > 1)
            vid = deviceInstanceIDItems[1].contains("VID_") ? deviceInstanceIDItems[1] : "";

        if (deviceInstanceIDItems.count() > 2)
            pid = deviceInstanceIDItems[2].contains("PID_") ? deviceInstanceIDItems[2] : "";

        if (deviceInstanceIDItems.count() > 3)
            mi = deviceInstanceIDItems[3].contains("MI_") ? deviceInstanceIDItems[3] : "";

        if (!vid.isEmpty())
            qDebug() << "    vid:  " << vid;
        if (!pid.isEmpty())
            qDebug() << "    pid: " << pid;
        if (!mi.isEmpty())
            qDebug() << "    mi: " << mi;

    }

    return "";
}

QString USBDevices::getSerialNum(HDEVINFO hDevInfo)
{
    // Get a context structure for the device interface
       // of a device information set.
       BYTE Buf[1024];
       PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
          (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
       SP_DEVICE_INTERFACE_DATA         spdid;
       SP_DEVINFO_DATA                  spdd;

       spdid.cbSize = sizeof( spdid );

       DWORD dwIndex = 0;
       while ( true )
       {
          if ( ! SetupDiEnumDeviceInterfaces( hDevInfo, NULL,
                                              //&GUID_DEVINTERFACE_USB_DISK,
                                              &my_guid,
                                              dwIndex, &spdid ))
          {
            qDebug() << "GetLastError code" << GetLastError();
            break;
          }

          DWORD dwSize = 0;
          SetupDiGetDeviceInterfaceDetail( hDevInfo, &spdid, NULL,
                                           0, &dwSize, NULL );

          if (( dwSize != 0 ) && ( dwSize <= sizeof( Buf )))
          {
             pspdidd->cbSize = sizeof( *pspdidd ); // 5 Bytes!

             ZeroMemory((PVOID)&spdd, sizeof(spdd));
             spdd.cbSize = sizeof(spdd);

             long res = SetupDiGetDeviceInterfaceDetail(
                hDevInfo, &spdid, pspdidd,
                dwSize, &dwSize, &spdd );
//                 if ( res )
//                 {
//                    HANDLE hDrive = CreateFile( pspdidd->DevicePath,0,
//                                                FILE_SHARE_READ | FILE_SHARE_WRITE,
//                                                NULL, OPEN_EXISTING, 0, NULL );
//                    if ( hDrive != INVALID_HANDLE_VALUE )
//                    {
//                       DWORD usbDeviceNumber = getDeviceNumber( hDrive );

//                       if ( usbDeviceNumber == volumeDeviceNumber )
//                       {
//                          fprintf( "%s", pspdidd->DevicePath );
//                       }
//                    }
//                    CloseHandle( hDrive );
//                 }

             qDebug() << "Device Path" << pspdidd->DevicePath;

             QString devicePath = QString::fromWCharArray( pspdidd->DevicePath );

             return devicePath;
          }
          dwIndex++;
       }

       return "";
}

问题出在这部分代码:

  if ( ! SetupDiEnumDeviceInterfaces( hDevInfo, NULL,
                                      //&GUID_DEVINTERFACE_USB_DISK,
                                      &my_guid,
                                      dwIndex, &spdid ))
  {
    qDebug() << "GetLastError code" << GetLastError();
    break;
  }

返回错误代码 269,因此它不检索任何信息。我尝试提供几个不同的 GUID,我认为它们可以解决问题,但它没有,而且我不确定我应该提供什么 GUID,因为我的不是存储设备。

【问题讨论】:

    标签: c++ windows usb


    【解决方案1】:

    您应该使用启用标志DIGCF_DEVICEINTERFACE 和一些接口类GUID 调用SetupDiGetClassDevs。然后,您使用相同的 GUID 调用 SetupDiEnumDeviceInterfaces。在你的情况下,我认为GUID_DEVINTERFACE_USB_DEVICE 会完成这项工作。

    您可以找到here 的合格 GUID。

    【讨论】:

      猜你喜欢
      • 2018-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      相关资源
      最近更新 更多