Windows系统下如何通过厂商ID和产品ID获取USB设备路径
仅通过Vendor ID和Product ID查找USB设备路径(SetupDi系列函数实现)
不需要额外的设备实例ID,仅用VID和PID就能通过SetupDi系列函数筛选目标USB设备,核心是通过读取设备的**硬件ID(Hardware ID)**进行匹配,以下是具体实现步骤和代码:
实现步骤
- 获取USB设备信息集:调用
SetupDiGetClassDevs获取当前系统中所有已连接的USB设备接口集合,指定DIGCF_PRESENT(仅枚举已连接设备)和DIGCF_DEVICEINTERFACE(枚举设备接口而非设备实例)。 - 遍历设备接口:用
SetupDiEnumDeviceInterfaces逐个枚举设备信息集中的设备接口。 - 匹配VID/PID:对每个设备接口,调用
SetupDiGetDeviceRegistryProperty读取其硬件ID,解析硬件ID字符串(格式通常为USB\VID_XXXX&PID_YYYY&...),匹配目标VID和PID。 - 获取设备路径:匹配成功后,调用
SetupDiGetDeviceInterfaceDetail获取可用于创建设备句柄的设备路径。
代码示例(C++)
#include <windows.h> #include <setupapi.h> #include <initguid.h> #include <usbiodef.h> #include <iostream> #include <vector> #include <string> #pragma comment(lib, "setupapi.lib") bool FindUsbDevicePath(WORD targetVid, WORD targetPid, std::wstring& outDevicePath) { HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (deviceInfoSet == INVALID_HANDLE_VALUE) { std::cerr << "SetupDiGetClassDevs failed, error: " << GetLastError() << std::endl; return false; } SP_DEVICE_INTERFACE_DATA deviceInterfaceData = {0}; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (DWORD i = 0; SetupDiEnumDeviceInterfaces(deviceInfoSet, nullptr, &GUID_DEVINTERFACE_USB_DEVICE, i, &deviceInterfaceData); i++) { // 先获取所需缓冲区大小 DWORD requiredSize = 0; SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, nullptr, 0, &requiredSize, nullptr); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { std::cerr << "SetupDiGetDeviceInterfaceDetail (size check) failed, error: " << GetLastError() << std::endl; continue; } // 分配缓冲区 std::vector<BYTE> detailBuffer(requiredSize); PSP_DEVICE_INTERFACE_DETAIL_DATA pDetailData = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(detailBuffer.data()); pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); SP_DEVINFO_DATA devInfoData = {0}; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, pDetailData, requiredSize, nullptr, &devInfoData)) { std::cerr << "SetupDiGetDeviceInterfaceDetail failed, error: " << GetLastError() << std::endl; continue; } // 读取硬件ID WCHAR hardwareIdBuffer[1024] = {0}; if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData, SPDRP_HARDWAREID, nullptr, reinterpret_cast<PBYTE>(hardwareIdBuffer), sizeof(hardwareIdBuffer), nullptr)) { std::cerr << "SetupDiGetDeviceRegistryProperty failed, error: " << GetLastError() << std::endl; continue; } // 解析硬件ID,匹配VID/PID WCHAR* currentId = hardwareIdBuffer; while (*currentId != L'\0') { std::wstring idStr(currentId); // 查找VID和PID的位置 size_t vidPos = idStr.find(L"VID_"); size_t pidPos = idStr.find(L"PID_"); if (vidPos != std::wstring::npos && pidPos != std::wstring::npos) { WORD vid = static_cast<WORD>(wcstoul(idStr.substr(vidPos + 4, 4).c_str(), nullptr, 16)); WORD pid = static_cast<WORD>(wcstoul(idStr.substr(pidPos + 4, 4).c_str(), nullptr, 16)); if (vid == targetVid && pid == targetPid) { outDevicePath = pDetailData->DevicePath; SetupDiDestroyDeviceInfoList(deviceInfoSet); return true; } } currentId += wcslen(currentId) + 1; } } SetupDiDestroyDeviceInfoList(deviceInfoSet); return false; } int main() { WORD targetVid = 0x1234; // 替换为你的目标厂商ID WORD targetPid = 0x5678; // 替换为你的目标产品ID std::wstring devicePath; if (FindUsbDevicePath(targetVid, targetPid, devicePath)) { std::wcout << L"找到目标设备路径: " << devicePath << std::endl; // 后续可使用CreateFile打开设备句柄,发送控制码 HANDLE hDevice = CreateFile(devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); if (hDevice != INVALID_HANDLE_VALUE) { // 这里可以发送IOCTL控制码 CloseHandle(hDevice); } } else { std::cerr << "未找到目标设备" << std::endl; } return 0; }
关键说明
- GUID_DEVINTERFACE_USB_DEVICE:这是USB设备接口的类GUID,用于筛选所有USB设备接口,确保我们获取的是可直接打开的设备路径。
- 硬件ID解析:每个设备的硬件ID是多个以NULL分隔的字符串,最后以双NULL结尾,需要逐个遍历检查是否包含匹配的VID和PID。
- 错误处理:所有SetupDi系列函数调用后都要检查返回值,通过
GetLastError()排查问题。 - 设备路径使用:获取到的设备路径可直接传入
CreateFile创建设备句柄,之后即可调用DeviceIoControl发送控制码。
内容的提问来源于stack exchange,提问作者Jan200101
相关产品推荐
相关产品推荐

