How do I know if a device has been disconnected by a user?

Using the device manager, the user can explicitly enable / disable the device, as shown in the following figure.

enter image description here

For this device, I want to know if it is currently in the disabled / on state of the user.

I tried the following approaches

  • CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); I was hoping the presence of DN_STARTED , or DN_DRIVER_LOADED would tell me that. But they can be zero even when the driver loads / unloads the OS, when the device connects / disconnects. For example, a device that is turned on and for which a driver is loaded. DN_STARTED will be 1 , but when we disconnect the device, it is set to zero before the device record is deleted from the device manager.
  • SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...) I, although the status CM_INSTALL_STATE_INSTALLED should mean that the device is turned on. But the function returns this state even for disconnected devices.
  • Using WMI, I was able to get the necessary information, but I used wmi in PowerShell. I do not want to use wmi, since it is quite difficult to implement in native C ++. I used the following query.

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

ConfigManagerErrorCode in the above request, if set to 22, means the device was disconnected, 21 means that windows remove the device

I am looking for a solution without wmi.

+5
source share
1 answer

Information can be obtained from the device problem code. There are two ways that I could find to get it.

  • Use SetupDiGetDeviceProperty() to query DEVPKEY_Device_ProblemCode .
  • Use CM_Get_DevNode_Status() the problem code will be present in the second argument after the call.

Problem code 22 ( CM_PROB_DISABLED ) means that the device was explicitly disconnected by the user using the device manager or other such utility.

Code example

 #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; } 

Output result

 problem 0 deviceProblemCode 0 problem 22 deviceProblemCode 22 

In the question, you can see that Intel(R) HD Graphics 530 turned on, and the NVIDIA Quadro M1000M turned off. Therefore, at the output, we received problem code 0 and problem code 22 ( CM_PROB_DISABLED ).

+1
source

Source: https://habr.com/ru/post/1273380/


All Articles