如何知道设备是否已被用户明确禁用?

Sah*_*ngh 5 c++ wmi device-driver device-manager setupapi

使用设备管理器,用户可以明确启用/禁用设备,如下图所示.

在此输入图像描述

对于给定的设备,我想知道它是否当前处于用户禁用/启用状态.

我尝试了以下方法

  1. CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0);我希望存在DN_STARTED,或者DN_DRIVER_LOADED会告诉我.但是,当设备连接/断开连接时,即使操作系统正在加载/卸载驱动程序,这些也可能为零.例如,已启用并为其加载驱动程序的设备.DN_STARTED将是1,但当我们断开设备时,它将设置为零,然后从设备管理器中删除设备的条目.
  2. SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...)我的状态CM_INSTALL_STATE_INSTALLED应该意味着设备已启用.但即使对于禁用的设备,该函数也会返回此状态.
  3. 使用WMI我能够获得所需的信息,但我在PowerShell中使用了wmi.我不想使用wmi,因为在本机c ++中实现起来非常困难.我使用了以下查询.

    Select Name, Availability, ConfigManagerErrorCode, ConfigManagerUserConfig from Win32_PnPEntity where Name = 'NVIDIA Quadro M1000M'

上述查询中的ConfigManagerErrorCode,如果设置为22,表示设备已被禁用,21表示Windows正在删除设备

我正在寻找一个非wmi解决方案.

Sah*_*ngh 3

该信息可以从设备的问题代码中获取。我可以找到两种方法来获取它。

  1. 用于SetupDiGetDeviceProperty()查询DEVPKEY_Device_ProblemCode
  2. 使用CM_Get_DevNode_Status()问题代码将出现在调用后的第二个参数中。

问题代码 22 ( CM_PROB_DISABLED) 表示用户已通过使用设备管理器或其他此类实用程序显式禁用该设备。

示例代码

#include "stdafx.h"
#include <Windows.h>
#include <SetupAPI.h>
#include <Cfgmgr32.h>
#include <devguid.h>
#include <initguid.h>
#include "devpkey.h"
#include <algorithm>
#include <iostream>

using namespace std;

int main()
{
    HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0); //only getting for GPUs on the machine

    if (INVALID_HANDLE_VALUE != hDevInfo)
    {
        SP_DEVINFO_DATA data;
        data.cbSize = (DWORD)sizeof(data);

        for (unsigned int nIndex = 0; ::SetupDiEnumDeviceInfo(hDevInfo, nIndex, &data); nIndex++)
        {
            ULONG status = 0, problem = 0;
            CONFIGRET cr = ::CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); //after the call 'problem' variable will have the problem code
            if (CR_SUCCESS == cr)
            {
                cout << " problem " << problem <<endl;
                if(problem == CM_PROB_DISABLED)
                { /*Do Something*/ }

                DEVPROPTYPE propertyType;
                const DWORD propertyBufferSize = 100;
                BYTE propertyBuffer[propertyBufferSize];
                std::fill(begin(propertyBuffer), end(propertyBuffer), BYTE(0));
                DWORD requiredSize = 0;

                if (SetupDiGetDeviceProperty(hDevInfo, &data, &DEVPKEY_Device_ProblemCode, &propertyType, propertyBuffer, propertyBufferSize, &requiredSize, 0)) //after the call 'propertyBuffer' will have error codes
                {
                    unsigned long deviceProblemCode = *((unsigned long*)propertyBuffer);
                    cout << " deviceProblemCode " << deviceProblemCode << endl;
                if(problem == CM_PROB_DISABLED)
                { /*Do Something*/ }

                }
            }
        }
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

样本输出

problem 0
deviceProblemCode 0
problem 22
deviceProblemCode 22
Run Code Online (Sandbox Code Playgroud)

在问题中可以看到Intel(R) HD Graphics 530已启用和NVIDIA Quadro M1000M已禁用。因此,在输出中我们得到问题代码 0 和问题代码 22 ( CM_PROB_DISABLED)。