EnumDisplayDevices vs WMI Win32_DesktopMonitor, how to detect active monitors?
c++, winapi, windows, wmi
Solution
This is my current work-in-progress code for detecting the monitor device id, reliably.
CString DeviceID;
DISPLAY_DEVICE dd;
dd.cb = sizeof(dd);
DWORD dev = 0;
// device index
int id = 1;
// monitor number, as used by Display Properties > Settings
while (EnumDisplayDevices(0, dev, &dd, 0))
{
DISPLAY_DEVICE ddMon;
ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
DWORD devMon = 0;
while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0))
{
if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE &&
!(ddMon.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
{
DeviceID.Format (L"%s", ddMon.DeviceID);
DeviceID = DeviceID.Mid (8, DeviceID.Find (L"\\", 9) - 8);
}
devMon++;
ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
}
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
dev++;
}
Problem
For my current C++ project I need to detect a unique string for every monitor that is connected and active on a large number of computers. Research has pointed to 2 options Use WMI and query the Win32_DesktopMonitor for all active monitors. Use the PNPDeviceID for unique identification of monitors. Use the EnumDisplayDevices API, and dig down to get the device ID. I'm interested in using the device id for unique model identification because monitors using the default plug and play driver will report a generic string as the monitor name "default plug and play monitor" I have been experiencing issues with the WMI method, it seems to be only returning 1 monitor on my Vista machine, looking at the doco it turns out it does not work as expected on non WDDM devices. The EnumDisplayDevices seems to be a little problematic to get going when it runs from a background service (especially on Vista), If it's in session 0 it will return no info. Has anyone else had to do something similar (find unique model string for all connected active monitors?) What approach worked best?