如何枚举窗口中的轮毂上的USB设备

发布于 2025-02-04 08:45:22 字数 2541 浏览 5 评论 0原文

我想获取Windows计算机上所有的USB设备的列表。以下程序完美地执行此操作,除了它仅找到直接连接到PC的USB设备,包括轮毂,但不连接到集线器上的设备:

void MainWindow::getConnectedUSB()
{
    GUID GUID_DEVINTERFACE_USB_HUB={ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
    GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
    GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER={ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27}};
    getConnectedUSB(&GUID_DEVINTERFACE_USB_DEVICE);
    getConnectedUSB(&GUID_DEVINTERFACE_USB_HUB);
    getConnectedUSB(&GUID_DEVINTERFACE_USB_HOST_CONTROLLER);
}

void MainWindow::getConnectedUSB(GUID *ClassGuid)
{
    HDEVINFO                         hDevInfo;
    SP_DEVICE_INTERFACE_DATA         DevIntfData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA DevIntfDetailData;
    SP_DEVINFO_DATA                  DevData;

    DWORD dwMemberIdx = 0;
    DWORD dwSize;

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

    if (hDevInfo != INVALID_HANDLE_VALUE)
    {
        DevIntfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

        SetupDiEnumDeviceInterfaces(hDevInfo, NULL, ClassGuid, dwMemberIdx, &DevIntfData);

        while(GetLastError() != ERROR_NO_MORE_ITEMS)
        {
            DevData.cbSize = sizeof(DevData);
            SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, NULL, 0, &dwSize, NULL);
            DevIntfDetailData = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize));
            DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

            if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, DevIntfDetailData, dwSize, &dwSize, &DevData))
            {
                QString devicePath = QString::fromWCharArray(DevIntfDetailData->DevicePath);
                qDebug() << devicePath;
                if (devicePath.startsWith("\\\\?\\usb#vid"))
                        m_connectedUSB.push_back(devicePath);
            }

            HeapFree(GetProcessHeap(), 0, DevIntfDetailData);
            SetupDiEnumDeviceInterfaces(hDevInfo, NULL, ClassGuid, ++dwMemberIdx, &DevIntfData);
        }

        SetupDiDestroyDeviceInfoList(hDevInfo);
    }
}

它使用一点QString Magic将DevicePath数据收集到M_ConnectedUSB中,该数据是QStringList,但否则,这是所有常规的Windows系统调用。我还需要做些什么才能使其迭代与轮毂相连的设备(以及连接到轮毂等的枢纽,等等 - 我希望它能获得所有内容)?

I want to get a list of all the USB devices attached to a Windows machine. The following program does this perfectly except that it only finds the USB devices attached directly to the PC including hubs but not the devices attached to the hubs:

void MainWindow::getConnectedUSB()
{
    GUID GUID_DEVINTERFACE_USB_HUB={ 0xf18a0e88, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
    GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
    GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER={ 0x3abf6f2d, 0x71c4, 0x462a, {0x8a, 0x92, 0x1e, 0x68, 0x61, 0xe6, 0xaf, 0x27}};
    getConnectedUSB(&GUID_DEVINTERFACE_USB_DEVICE);
    getConnectedUSB(&GUID_DEVINTERFACE_USB_HUB);
    getConnectedUSB(&GUID_DEVINTERFACE_USB_HOST_CONTROLLER);
}

void MainWindow::getConnectedUSB(GUID *ClassGuid)
{
    HDEVINFO                         hDevInfo;
    SP_DEVICE_INTERFACE_DATA         DevIntfData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA DevIntfDetailData;
    SP_DEVINFO_DATA                  DevData;

    DWORD dwMemberIdx = 0;
    DWORD dwSize;

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

    if (hDevInfo != INVALID_HANDLE_VALUE)
    {
        DevIntfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

        SetupDiEnumDeviceInterfaces(hDevInfo, NULL, ClassGuid, dwMemberIdx, &DevIntfData);

        while(GetLastError() != ERROR_NO_MORE_ITEMS)
        {
            DevData.cbSize = sizeof(DevData);
            SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, NULL, 0, &dwSize, NULL);
            DevIntfDetailData = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize));
            DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

            if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, DevIntfDetailData, dwSize, &dwSize, &DevData))
            {
                QString devicePath = QString::fromWCharArray(DevIntfDetailData->DevicePath);
                qDebug() << devicePath;
                if (devicePath.startsWith("\\\\?\\usb#vid"))
                        m_connectedUSB.push_back(devicePath);
            }

            HeapFree(GetProcessHeap(), 0, DevIntfDetailData);
            SetupDiEnumDeviceInterfaces(hDevInfo, NULL, ClassGuid, ++dwMemberIdx, &DevIntfData);
        }

        SetupDiDestroyDeviceInfoList(hDevInfo);
    }
}

It uses a little bit of QString magic to collect the DevicePath data into m_connectedUSB which is a QStringList but otherwise it is all regular Windows system calls. What more do I need to do get it to iterate around the devices attached to hubs (and hubs attached to hubs and so forth - I'd like it to get everything)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

∞觅青森が 2025-02-11 08:45:22

这并不是一个很好的答案,因为它所做的就是打电话给Powershell完成工作。但是,它总比没有好,而且由于它将数据返回为JSON字符串,因此应该相当强大。

int MainWindow::getConnectedPNP()
{
    QProcess process;
    QString program = "PowerShell";
    QStringList arguments;
    // PowerShell -Command "& {Get-PnpDevice | Select-Object Status,Class,FriendlyName,InstanceId,Manufacturer,Present | ConvertTo-Json}"
    arguments << "-Command" << "& {Get-PnpDevice | Select-Object Status,Class,FriendlyName,InstanceId,Manufacturer,Present | ConvertTo-Json}";
    process.start(program, arguments);
    if (!process.waitForStarted()) return __LINE__;
    if (!process.waitForFinished()) return __LINE__;
    QByteArray result = process.readAll();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(result);
    if (jsonDoc.isNull()) return __LINE__;
    if (!jsonDoc.isArray()) return __LINE__;
    QJsonArray jsonArray = jsonDoc.array();
    for (auto &&it : jsonArray)
    {
        if (!it.isObject()) continue;
        QJsonObject obj = it.toObject();
        if (obj["Status"].toString() != "OK") continue;
        if (obj["Present"].toBool() != true) continue;
        m_connectedPNPClass.push_back(obj["Class"].toString());
        m_connectedPNPFriendlyName.push_back(obj["FriendlyName"].toString());
        m_connectedPNPInstanceId.push_back(obj["InstanceId"].toString());
        m_connectedPNPManufacturer.push_back(obj["Manufacturer"].toString());
    }
    if (m_connectedPNPClass.size() == 0) return __LINE__;
    return 0;
}

它返回了系统上注册的所有PNP设备的大列表,在此代码中,我只是将返回的字符串添加到QStringLists中。如果您不做Select-Object,则会获得更大的JSON字符串,其中包含更多信息。要获取USB设备,您只需要查看InstanceID字符串,因为它以USB开头。它不是绝对理想的,因为它似乎可以为某些设备返回多行,当然,这取决于Powershell在路径上。从好的方面来说,友好名值是一件方便的事情。

This isn't a great answer since all it does is call PowerShell to get the work done. However it is much better than nothing, and because it returns the data as a JSON string it should be fairly robust.

int MainWindow::getConnectedPNP()
{
    QProcess process;
    QString program = "PowerShell";
    QStringList arguments;
    // PowerShell -Command "& {Get-PnpDevice | Select-Object Status,Class,FriendlyName,InstanceId,Manufacturer,Present | ConvertTo-Json}"
    arguments << "-Command" << "& {Get-PnpDevice | Select-Object Status,Class,FriendlyName,InstanceId,Manufacturer,Present | ConvertTo-Json}";
    process.start(program, arguments);
    if (!process.waitForStarted()) return __LINE__;
    if (!process.waitForFinished()) return __LINE__;
    QByteArray result = process.readAll();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(result);
    if (jsonDoc.isNull()) return __LINE__;
    if (!jsonDoc.isArray()) return __LINE__;
    QJsonArray jsonArray = jsonDoc.array();
    for (auto &&it : jsonArray)
    {
        if (!it.isObject()) continue;
        QJsonObject obj = it.toObject();
        if (obj["Status"].toString() != "OK") continue;
        if (obj["Present"].toBool() != true) continue;
        m_connectedPNPClass.push_back(obj["Class"].toString());
        m_connectedPNPFriendlyName.push_back(obj["FriendlyName"].toString());
        m_connectedPNPInstanceId.push_back(obj["InstanceId"].toString());
        m_connectedPNPManufacturer.push_back(obj["Manufacturer"].toString());
    }
    if (m_connectedPNPClass.size() == 0) return __LINE__;
    return 0;
}

It returns a big list of all the PNP devices registered on the system and in this code I am just adding the returned strings to QStringLists. If you don't do the Select-Object you get an even bigger JSON string with even more information. To get the USB devices you just have to look at the InstanceId string because it starts with USB. It is not absolutely ideal because it seems to return multiple lines for some devices, and of course it depends on PowerShell being on the path. On the plus side, the FriendlyName value is a handy thing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文