Windows程序无法获取设备SP_DEVINFO_DATA问题排查
问题:SetupDiCreateDeviceInfoA调用失败,无法获取SP_DEVINFO_DATA
我编写了以下无法正常运行的示例代码,当前问题是无法通过SetupDiCreateDeviceInfoA成功获取SP_DEVINFO_DATA(程序输出‘ERROR: Could not obtain SP_DEVINFO_DATA.’),请问哪里操作有误?
#pragma comment (lib, "Setupapi.lib") #pragma comment (lib, "newdev.lib") #include <windows.h> #include <newdev.h> #include <setupapi.h> #include <iostream> int main() { GUID guid; HRESULT hResult = CLSIDFromString( L"{4d36e96b-e325-11ce-bfc1-08002be10318}", (LPCLSID) &guid); if (hResult == CO_E_CLASSSTRING) { std::cerr << "ERROR: Bad GUID string.\n"; return EXIT_FAILURE; } HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(&guid, NULL); if (hDevInfo == INVALID_HANDLE_VALUE) { std::cerr << "ERROR: Could not obtain HDEVINFO.\n"; return EXIT_FAILURE; } SP_DEVINFO_DATA deviceInfoData; BOOL gotDeviceInfoData = SetupDiCreateDeviceInfoA( hDevInfo, "HID\\ASUE140D&COL04\\4&67A7B61&0&0003", &guid, NULL, NULL, 0, &deviceInfoData); if (!gotDeviceInfoData) { std::cerr << "ERROR: Could not obtain SP_DEVINFO_DATA.\n"; return EXIT_FAILURE; } BOOL removeStatus = SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &deviceInfoData); if (!removeStatus) { std::cerr << "ERROR: SetupDiCallClassInstaller failed. " << "Could not remove the device.\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; }
错误分析与修正方案
1. 未初始化SP_DEVINFO_DATA的cbSize字段
Windows API中大部分结构体要求先设置cbSize字段为结构体的大小,否则API会因参数无效直接失败。你需要在调用SetupDiCreateDeviceInfoA前添加:
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
2. 使用了错误的API函数
SetupDiCreateDeviceInfoA的作用是创建新的设备信息条目,而非获取系统中已存在的设备信息。你的需求是删除已存在的设备,应该改用SetupDiOpenDeviceInfo打开目标设备条目,前提是先用SetupDiGetClassDevs获取对应类的设备列表。
3. 未获取具体错误码
API调用失败后,调用GetLastError()可以获取精确错误码,能快速定位问题根源(比如权限不足、设备不存在等)。
修正后的代码
#pragma comment (lib, "Setupapi.lib") #pragma comment (lib, "newdev.lib") #include <windows.h> #include <newdev.h> #include <setupapi.h> #include <iostream> #include <string> int main() { GUID hidGuid; HRESULT hResult = CLSIDFromString(L"{4d36e96b-e325-11ce-bfc1-08002be10318}", (LPCLSID)&hidGuid); if (hResult == CO_E_CLASSSTRING) { std::cerr << "ERROR: Bad GUID string.\n"; return EXIT_FAILURE; } // 获取当前存在的HID类设备列表 HDEVINFO hDevInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hDevInfo == INVALID_HANDLE_VALUE) { std::cerr << "ERROR: Could not obtain HDEVINFO. Error: " << GetLastError() << "\n"; return EXIT_FAILURE; } SP_DEVINFO_DATA deviceInfoData{}; deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); // 枚举设备,匹配目标硬件ID const std::string targetHardwareId = "HID\\ASUE140D&COL04\\4&67A7B61&0&0003"; BOOL found = FALSE; for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &deviceInfoData); i++) { char hardwareId[256]; if (SetupDiGetDeviceRegistryPropertyA(hDevInfo, &deviceInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)hardwareId, sizeof(hardwareId), NULL)) { if (std::string(hardwareId) == targetHardwareId) { found = TRUE; break; } } } if (!found) { std::cerr << "ERROR: Target device not found. Error: " << GetLastError() << "\n"; SetupDiDestroyDeviceInfoList(hDevInfo); return EXIT_FAILURE; } // 配置删除参数 SP_REMOVEDEVICE_PARAMS removeParams{}; removeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); removeParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; removeParams.Scope = DI_REMOVEDEVICE_GLOBAL; // 全局删除设备及关联驱动,可按需调整 if (!SetupDiSetClassInstallParams(hDevInfo, &deviceInfoData, &removeParams.ClassInstallHeader, sizeof(removeParams))) { std::cerr << "ERROR: SetupDiSetClassInstallParams failed. Error: " << GetLastError() << "\n"; SetupDiDestroyDeviceInfoList(hDevInfo); return EXIT_FAILURE; } // 执行删除操作 BOOL removeStatus = SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, &deviceInfoData); if (!removeStatus) { std::cerr << "ERROR: SetupDiCallClassInstaller failed. Could not remove the device. Error: " << GetLastError() << "\n"; SetupDiDestroyDeviceInfoList(hDevInfo); return EXIT_FAILURE; } std::cout << "Device removed successfully.\n"; SetupDiDestroyDeviceInfoList(hDevInfo); return EXIT_SUCCESS; }
内容的提问来源于stack exchange,提问作者coderodde
相关产品推荐
相关产品推荐

