如何通过PDEV_BROADCAST_DEVICEINTERFACE获取USB设备详细信息
从WM_DEVICECHANGE获取USB设备详细信息
你当前通过PDEV_BROADCAST_DEVICEINTERFACE拿到的dbcc_name只是设备的接口路径,本身不包含厂商、描述、容量这类详细数据。要获取这些信息,需要结合Windows的SetupAPI和磁盘IO控制函数,以下是具体实现方案:
一、获取设备基本信息(名称、厂商、描述)
通过设备接口路径,我们可以从系统注册表中读取设备的属性信息,需要用到SetupAPI系列函数:
前置准备
- 包含头文件:
#include <SetupAPI.h>、#include <InitGuid.h> - 链接库:
#pragma comment(lib, "SetupAPI.lib")
实现代码
在你的DBT_DEVICEARRIVAL分支中添加以下逻辑:
case DBT_DEVICEARRIVAL: { std::cout << "new device connected: " << path << std::endl; // 1. 初始化设备信息集合(以磁盘设备为例,可根据需求更换GUID) HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDevInfo == INVALID_HANDLE_VALUE) break; SP_DEVICE_INTERFACE_DATA deviceInterfaceData = {0}; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // 2. 打开目标设备接口 if (!SetupDiOpenDeviceInterface(hDevInfo, lpdbv->dbcc_name, 0, &deviceInterfaceData)) { SetupDiDestroyDeviceInfoList(hDevInfo); break; } // 3. 获取设备接口详情,拿到SP_DEVINFO_DATA DWORD requiredSize = 0; SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL); std::vector<BYTE> detailBuffer(requiredSize); SP_DEVICE_INTERFACE_DETAIL_DATA* pDetailData = reinterpret_cast<SP_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(hDevInfo, &deviceInterfaceData, pDetailData, requiredSize, NULL, &devInfoData)) { // 4. 读取各类设备属性 WCHAR buffer[256] = {0}; // 友好名称 if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, reinterpret_cast<PBYTE>(buffer), sizeof(buffer), NULL)) std::wcout << L"Friendly Name: " << buffer << std::endl; // 设备描述 memset(buffer, 0, sizeof(buffer)); if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_DEVICEDESC, NULL, reinterpret_cast<PBYTE>(buffer), sizeof(buffer), NULL)) std::wcout << L"Device Description: " << buffer << std::endl; // 厂商名称 memset(buffer, 0, sizeof(buffer)); if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_MFG, NULL, reinterpret_cast<PBYTE>(buffer), sizeof(buffer), NULL)) std::wcout << L"Manufacturer: " << buffer << std::endl; } SetupDiDestroyDeviceInfoList(hDevInfo); break; }
二、获取存储设备容量
要获取USB存储设备的容量,需要通过CreateFile打开设备,再用DeviceIoControl发送磁盘控制指令:
实现代码
同样在DBT_DEVICEARRIVAL分支中添加:
// 打开设备句柄 HANDLE hDevice = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice != INVALID_HANDLE_VALUE) { DISK_GEOMETRY_EX geometryEx = {0}; DWORD bytesReturned = 0; // 获取磁盘几何信息,计算总容量 if (DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &geometryEx, sizeof(geometryEx), &bytesReturned, NULL)) { ULONGLONG totalBytes = geometryEx.DiskSize.QuadPart; ULONGLONG totalGB = totalBytes / (1024 * 1024 * 1024); std::cout << "Total Capacity: " << totalGB << " GB" << std::endl; } CloseHandle(hDevice); }
注意事项
- 设备类GUID:上述代码用了
GUID_DEVINTERFACE_DISK(磁盘设备),如果是其他类型USB设备(比如摄像头、打印机),需要替换为对应类的GUID - 权限问题:
CreateFile需要足够的读取权限,确保程序以合适的权限运行 - 错误处理:实际开发中要严格检查每个API的返回值,避免空指针或无效句柄导致崩溃
内容的提问来源于stack exchange,提问作者TienThanh
相关产品推荐
相关产品推荐

