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

时间:2017-11-15 07:09:26

标签: c++ wmi device-driver device-manager setupapi

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

enter image description here

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

我尝试了以下方法

  1. CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0);我希望DN_STARTEDDN_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'

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

    我正在寻找一种非wmi解决方案。

1 个答案:

答案 0 :(得分:2)

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

  1. 使用SetupDiGetDeviceProperty()查询DEVPKEY_Device_ProblemCode
  2. 使用CM_Get_DevNode_Status()调用后第二个参数中将出现问题代码。
  3. 问题代码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;
    }
    

    示例输出

    problem 0
    deviceProblemCode 0
    problem 22
    deviceProblemCode 22
    

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