You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 15:27:40