如何知道设备是否已被用户明确禁用?
How to know if a device has been explicitly been disabled by user?
用户可以使用设备管理器明确 enable/disable 设备,如下图所示。
对于给定的设备,我想知道它当前是否处于用户 disabled/enabled 状态。
我尝试了以下方法
CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0);
我希望 DN_STARTED
或 DN_DRIVER_LOADED
的存在能告诉我这一点。但是即使驱动程序被OSloaded/unloaded,设备connects/disconnects,这些也可以为零。例如,已启用并加载了驱动程序的设备。 DN_STARTED
将是 1
,但是当我们断开设备连接时,它会在设备条目从设备管理器中删除之前设置为零。
SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...)
我虽然状态 CM_INSTALL_STATE_INSTALLED
应该意味着设备已启用。但是函数 returns 这个状态甚至适用于禁用的设备。
使用 WMI 我能够获得所需的信息,但我在 PowerShell 中使用了 wmi。我不想使用 wmi,因为它很难在本机 c++ 中实现。我使用了以下查询。
Select Name, Availability, ConfigManagerErrorCode, ConfigManagerUserConfig from Win32_PnPEntity where Name = 'NVIDIA Quadro M1000M'
上面查询中的ConfigManagerErrorCode,如果设置为22,表示设备已被禁用,21表示windows正在删除设备
我正在寻找非 wmi 解决方案。
该信息可以从设备的问题代码中获取。我有两种方法可以找到它。
- 使用
SetupDiGetDeviceProperty()
查询DEVPKEY_Device_ProblemCode
.
- 使用
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;
}
示例输出
problem 0
deviceProblemCode 0
problem 22
deviceProblemCode 22
问题中可以看到启用了Intel(R) HD Graphics 530
,禁用了NVIDIA Quadro M1000M
。因此在输出中我们得到了问题代码 0 和问题代码 22 (CM_PROB_DISABLED
).
用户可以使用设备管理器明确 enable/disable 设备,如下图所示。
对于给定的设备,我想知道它当前是否处于用户 disabled/enabled 状态。
我尝试了以下方法
CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0);
我希望DN_STARTED
或DN_DRIVER_LOADED
的存在能告诉我这一点。但是即使驱动程序被OSloaded/unloaded,设备connects/disconnects,这些也可以为零。例如,已启用并加载了驱动程序的设备。DN_STARTED
将是1
,但是当我们断开设备连接时,它会在设备条目从设备管理器中删除之前设置为零。SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...)
我虽然状态CM_INSTALL_STATE_INSTALLED
应该意味着设备已启用。但是函数 returns 这个状态甚至适用于禁用的设备。使用 WMI 我能够获得所需的信息,但我在 PowerShell 中使用了 wmi。我不想使用 wmi,因为它很难在本机 c++ 中实现。我使用了以下查询。
Select Name, Availability, ConfigManagerErrorCode, ConfigManagerUserConfig from Win32_PnPEntity where Name = 'NVIDIA Quadro M1000M'
上面查询中的ConfigManagerErrorCode,如果设置为22,表示设备已被禁用,21表示windows正在删除设备
我正在寻找非 wmi 解决方案。
该信息可以从设备的问题代码中获取。我有两种方法可以找到它。
- 使用
SetupDiGetDeviceProperty()
查询DEVPKEY_Device_ProblemCode
. - 使用
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;
}
示例输出
problem 0
deviceProblemCode 0
problem 22
deviceProblemCode 22
问题中可以看到启用了Intel(R) HD Graphics 530
,禁用了NVIDIA Quadro M1000M
。因此在输出中我们得到了问题代码 0 和问题代码 22 (CM_PROB_DISABLED
).