C++ - WinAPI获取所有连接的USB设备列表

6
我将尝试创建一个程序,用于分类所有连接的USB设备及其端口GUID。
我找到了一个示例,可以获取所有连接的输入设备的信息:
#include <windows.h>
#include <iostream>

// Namespace
using namespace std;

// Main
int main()
{
    // Program
    cout << "USB Device Lister." << endl;

    // Get Number Of Devices
    UINT nDevices = 0;
    GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));

    // Got Any?
    if (nDevices < 1)
    {
        // Exit
        cout << "ERR: 0 Devices?";
        cin.get();
        return 0;
    }

    // Allocate Memory For Device List
    PRAWINPUTDEVICELIST pRawInputDeviceList;
    pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];

    // Got Memory?
    if (pRawInputDeviceList == NULL)
    {
        // Error
        cout << "ERR: Could not allocate memory for Device List.";
        cin.get();
        return 0;
    }

    // Fill Device List Buffer
    int nResult;
    nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));

    // Got Device List?
    if (nResult < 0)
    {
        // Clean Up
        delete[] pRawInputDeviceList;

        // Error
        cout << "ERR: Could not get device list.";
        cin.get();
        return 0;
    }

    // Loop Through Device List
    for (UINT i = 0; i < nDevices; i++)
    {
        // Get Character Count For Device Name
        UINT nBufferSize = 0;
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
            RIDI_DEVICENAME,                // Get Device Name
            NULL,                           // NO Buff, Want Count!
            &nBufferSize);                 // Char Count Here!

                                           // Got Device Name?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;

            // Next
            continue;
        }

        // Allocate Memory For Device Name
        WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];

        // Got Memory
        if (wcDeviceName == NULL)
        {
            // Error
            cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;

            // Next
            continue;
        }

        // Get Name
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
            RIDI_DEVICENAME,                // Get Device Name
            wcDeviceName,                   // Get Name!
            &nBufferSize);                 // Char Count

                                           // Got Device Name?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;

            // Clean Up
            delete[] wcDeviceName;

            // Next
            continue;
        }

        // Set Device Info & Buffer Size
        RID_DEVICE_INFO rdiDeviceInfo;
        rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
        nBufferSize = rdiDeviceInfo.cbSize;

        // Get Device Info
        nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
            RIDI_DEVICEINFO,
            &rdiDeviceInfo,
            &nBufferSize);

        // Got All Buffer?
        if (nResult < 0)
        {
            // Error
            cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;

            // Next
            continue;
        }

        // Mouse
        if (rdiDeviceInfo.dwType == RIM_TYPEMOUSE)
        {
            // Current Device
            cout << endl << "Displaying device " << i + 1 << " information. (MOUSE)" << endl;
            wcout << L"Device Name: " << wcDeviceName << endl;
            cout << "Mouse ID: " << rdiDeviceInfo.mouse.dwId << endl;
            cout << "Mouse buttons: " << rdiDeviceInfo.mouse.dwNumberOfButtons << endl;
            cout << "Mouse sample rate (Data Points): " << rdiDeviceInfo.mouse.dwSampleRate << endl;
            if (rdiDeviceInfo.mouse.fHasHorizontalWheel)
            {
                cout << "Mouse has horizontal wheel" << endl;
            }
            else
            {
                cout << "Mouse does not have horizontal wheel" << endl;
            }
        }

        // Keyboard
        else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
        {
            // Current Device
            cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
            wcout << L"Device Name: " << wcDeviceName << endl;
            cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
            cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
            cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
            cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
            cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
            cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;
        }

        // Some HID
        else // (rdi.dwType == RIM_TYPEHID)
        {
            // Current Device
            cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
            wcout << L"Device Name: " << wcDeviceName << endl;
            cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
            cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
            cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
            cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
            cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
        }

        // Delete Name Memory!
        delete[] wcDeviceName;
    }

    // Clean Up - Free Memory
    delete[] pRawInputDeviceList;

    // Exit
    cout << endl << "Finnished.";
    cin.get();
    return 0;
}

我尝试将此代码转换为获取所有连接的USB设备,但失败了。因此,我的问题是收集所需数据的最佳方法是什么?


1
我尝试将这段代码转换为获取所有连接的USB设备,但失败了。你能解释一下你做了什么吗?你遇到了什么问题?不要期望任何人会花时间猜测你提供的代码会产生什么结果... - Darko Djuric
1
这只是HID设备,不是所有的USB设备... - Alex K.
@DarkoDjuric 我没有添加自己的代码,因为它失败了,只是想说我尝试过了。 - Jenia
@AlexK. 我怎么可以获取其它的USB设备呢? - Jenia
@Jenia 失败了什么?编译失败了吗?无法读取任何设备?无法读取某些设备? - Darko Djuric
@DarkoDjuric 对不起,你是对的,我没有说清楚失败的原因。所以我无法获取其他USB设备,所有我的尝试都以与上面代码相同的结果结束。 - Jenia
2个回答

5
如果您想获取所有USB设备,而不仅仅是“输入”设备,则需要使用与设备管理器相同的API。例如,可以借助SetupDiGetClassDevs函数列出设备管理器显示的所有设备。要列出USB设备,需要使用枚举器参数设置为"USB"(枚举器是设备连接的总线,例如可以是"PCI", "PCMCIA", "USB"等主要计算机总线,也可以是由扩展设备提供的次要总线,例如"SCSI", "FTDIBUS"等)。有时您可能更感兴趣的是子设备而不是USB连接的父设备本身。

0
请记住,仅仅注释掉// (rdi.dwType == RIM_TYPEHID)是不够的,因为它只会打印出rdiDeviceInfo.hid.SOMETHING信息。如果设备不是HID,我期望会打印一些垃圾或类似的东西。
else // (rdi.dwType == RIM_TYPEHID)
        {
            // Current Device
            cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
            wcout << L"Device Name: " << wcDeviceName << endl;
            cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
            cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
            cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
            cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
            cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
        }

我建议您添加一些日志记录和断点(打印设备数量,打印所有设备名称等)。如果您无法解决问题,请粘贴用于测试的代码,并提供详细的问题说明。

更新:

GetRawInputDeviceList函数

备注

此函数返回的设备是鼠标、键盘和其他人体接口设备(HID)设备。

如果您的设备不是HID,则不要期望在列表中看到它。


从你的最后一句话中,我无法确定你是在说“此函数无法列出非HID设备”还是“根本没有非HID设备列表”。设备管理器确实可以列出非HID USB设备,你也可以这样做。 - Ben Voigt
根据上面引用的MSDN文档,GetRawInputDeviceList不会列出非HID设备。Microsoft建议使用GetRawInputDeviceInfo选项以获取有关连接设备的更详细信息。在引用的源代码中,两个函数都被使用,但只有HID设备被打印出来。 - Darko Djuric
对的,这两个函数创建的列表不包括非 HMI。但是你可以使用 SetupDi* 函数获取包含它们的列表。 - Ben Voigt
@Ben Voight 我同意。 - Darko Djuric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接