C++ 获取监视器的设备信息集:返回的句柄总是无效的\u句柄\u值

C++ 获取监视器的设备信息集:返回的句柄总是无效的\u句柄\u值,c++,winapi,device,guid,C++,Winapi,Device,Guid,我正在尝试列出当前连接到计算机的所有监视器的设备信息。我有一个函数可以做到这一点,它的90%都完成了,除非我使用第二个参数集(非空)调用函数SetupDiGetClassDevs(),然后函数总是失败(返回无效的句柄值) 当我调用GetLastError()时,我得到了错误13(十进制),即,“数据无效”,我不确定这是什么意思 出了什么问题?您能就发生了什么以及我如何解决它提供一些建议吗? My函数,尝试仅获取监视器的设备信息集,并输出每个监视器的详细信息(错误行已注释): void prin

我正在尝试列出当前连接到计算机的所有监视器的设备信息。我有一个函数可以做到这一点,它的90%都完成了,除非我使用第二个参数集(非空)调用函数
SetupDiGetClassDevs()
,然后函数总是失败(返回无效的句柄值)

当我调用
GetLastError()
时,我得到了错误13(十进制),即,
“数据无效”
,我不确定这是什么意思

出了什么问题?您能就发生了什么以及我如何解决它提供一些建议吗?

My函数,尝试仅获取监视器的设备信息集,并输出每个监视器的详细信息(错误行已注释):

void printDeviceData(GUID)
{
//设备类别:http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426
//系统设备类别:http://msdn.microsoft.com/en-us/library/windows/hardware/ff553428
//监控类GUI:{4d36e96e-e325-11ce-bfc1-08002be10318}
DWORD dataT=0;
PCTSTR监视器GUID=\u T(“”);
SP_DEVINFO_DATA deviceinfo={0};
DeviceInfo DATA.cbSize=sizeof(SP_DEVINFO_数据);
DeviceInfo.ClassGuid=guID;
//步骤1:仅获取监视器的设备信息集
//此处发生错误:SetupDiGetClassDevs()始终失败
//还尝试了参数2的这些值:“监视器”“PCI”,但都会导致函数返回无效的\u句柄\u值
HDEVINFO HDEVINFO=SetupDiGetClassDevs(&guID,_T(“{4d36e96e-e325-11ce-bfc1-08002be10318}”),NULL,DIGCF|u PRESENT | DIGCF|u DEVICEINTERFACE);
if(hDevInfo==无效的句柄值){
//outputLastError(失败1);
printf(“hDevInfo==无效的\u句柄\u值”);
返回;
}
else printf(“成功1\n”);
if(SetupDiGetSelectedDevice(hDevInfo,&DeviceInfo数据)==FALSE){
//outputLastError(_T(“SetupDiGetSelectedDevice(hDevInfo,&DeviceInfo数据)==FALSE”);
printf(“SetupDiGetSelectedDevice(hDevInfo,&DeviceInfo)==FALSE,%d,%x\n”,GetLastError(),GetLastError());
返回;
}
else printf(“成功2\n”);
//步骤2:对于每个监视器:输出设备信息
const unsigned int FLAG_NUM=30;
DWORD标志[]={SPDRP_FRIENDLYNAME,SPDRP_枚举器_NAME,SPDRP_物理_设备_对象_NAME,SPDRP_DEVICEDESC,
SPDRP_地址、SPDRP_总线号、SPDRP_总线型GUID、SPDRP_特性、SPDRP_类、SPDRP_类GUID、,
SPDRP_兼容EIDS、SPDRP_配置标志、SPDRP_设备、电源数据、SPDRP_开发类型、SPDRP_驱动程序、,
SPDRP_枚举器_名称、SPDRP_独占、SPDRP_硬件ID、SPDRP_安装_状态、SPDRP_LEGACYBUSTYPE、,
SPDRP_位置信息、SPDRP_位置路径、SPDRP_下部过滤器、SPDRP_制造商、,
SPDRP_物理_设备_对象_名称、SPDRP_用户界面_编号、SPDRP_用户界面_编号描述格式、SPDRP_上层过滤器、,
SPDRP_安全性_SDS、SPDRP_安全性、SPDRP_服务};

对于(inti=0;i,根据文档,枚举数必须设置为有效的设备实例ID,根据必须这样指定

“PCI\VEN_1000&DEV_0001&SUBSYS\u00000000&REV_02\1&08”

我还没有测试它,但我认为这就是无效数据的来源

HDEVINFO SetupDiGetClassDevs(
  _In_opt_  const GUID *ClassGuid,
  _In_opt_  PCTSTR Enumerator,     // According to MSDN this param MUST be set if I want Device Information for a specific class(Monitors)
  _In_opt_  HWND hwndParent,
  _In_      DWORD Flags
);
void printDeviceData(GUID guID)
{
    // Device Classes:        http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426
    // System Device Classes: http://msdn.microsoft.com/en-us/library/windows/hardware/ff553428
    // Monitor Class GUI:     {4d36e96e-e325-11ce-bfc1-08002be10318}

    DWORD dataT                    = 0;
    PCTSTR monitorGuID             = _T("");
    SP_DEVINFO_DATA deviceInfoData = {0};
    deviceInfoData.cbSize          = sizeof(SP_DEVINFO_DATA);
    deviceInfoData.ClassGuid       = guID;

    // Step 1: Get Device Information Set for Monitors only
    // ERROR OCCURS HERE: SetupDiGetClassDevs() always fails
    // Also tried these values for param 2: "Monitor" "PCI" but all cause the function to return INVALID_HANDLE_VALUE
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&guID, _T("{4d36e96e-e325-11ce-bfc1-08002be10318}"), NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        //outputLastError(_T("Fail 1"));
        printf("hDevInfo == INVALID_HANDLE_VALUE\n");
        return;
    }
    else printf("SUCCESS 1\n");

    if (SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE) {
        //outputLastError(_T("SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE"));
        printf("SetupDiGetSelectedDevice(hDevInfo, &deviceInfoData) == FALSE, %d, %x\n", GetLastError(), GetLastError());
        return;
    }
    else printf("SUCCESS 2\n");

    // Step 2: For each Monitor: Output Device information
    const unsigned int FLAG_NUM = 30;
    DWORD flags[] = {SPDRP_FRIENDLYNAME, SPDRP_ENUMERATOR_NAME, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, SPDRP_DEVICEDESC,
                        SPDRP_ADDRESS, SPDRP_BUSNUMBER, SPDRP_BUSTYPEGUID, SPDRP_CHARACTERISTICS, SPDRP_CLASS, SPDRP_CLASSGUID,
                        SPDRP_COMPATIBLEIDS, SPDRP_CONFIGFLAGS, SPDRP_DEVICE_POWER_DATA, SPDRP_DEVTYPE, SPDRP_DRIVER,
                        SPDRP_ENUMERATOR_NAME, SPDRP_EXCLUSIVE, SPDRP_HARDWAREID, SPDRP_INSTALL_STATE, SPDRP_LEGACYBUSTYPE,
                        SPDRP_LOCATION_INFORMATION, SPDRP_LOCATION_PATHS, SPDRP_LOWERFILTERS, SPDRP_MFG, 
                        SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, SPDRP_UI_NUMBER, SPDRP_UI_NUMBER_DESC_FORMAT, SPDRP_UPPERFILTERS, 
                        SPDRP_SECURITY_SDS, SPDRP_SECURITY, SPDRP_SERVICE };

    for (int i=0; i<=FLAG_NUM; i++) {
        DWORD buffersize = 0;
        LPTSTR buffer    = NULL;

        while (!SetupDiGetDeviceRegistryProperty(hDevInfo,  &deviceInfoData, flags[i], &dataT,
                                                    (PBYTE)buffer, buffersize, &buffersize))
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
                // Change the buffer size.
                if (buffer) 
                    LocalFree(buffer);
                buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
            }
            else {
                // Insert error handling here.
                break;
            }
        }

        printf("Data: %d: %s\n", i, buffer);
        if (buffer) 
            LocalFree(buffer);
    }

    SetupDiDestroyDeviceInfoList(hDevInfo);
}