EnumDisplayDevices vs WMI Win32_DesktopMonitor,如何检测活动的监视?
题
我现C++的项目,我需要测唯一串为每个监视器连接和活动在一个大数量的计算机。
研究指出了2个选择
使用WMI和查询的Win32_DesktopMonitor的所有活动的显示器。使用PNPDeviceID的独特识别的监视器。
使用EnumDisplayDevices API,并向下挖掘,获得的设备标识。
我有兴趣使用的设备id的独特模式的标识,因为监测使用的默认即插即驱动程序将报告的一个通用串的监测名"默认插播放监视器"
我已经遇到的问题与WMI方法,它似乎只有1返回监视器在我Vista机,在doco事实证明它不工作,预期在非WDDM设备。
EnumDisplayDevices似乎是一个小小的问题要走的时候它从一个背景服务(特别是在Vista),如果在会议0它将返回不信息。
有任何人不得不做一些事情相似(找到独特的模型字符串连接的所有活动的显示器?)
什么样的工作方法最好?
解决方案
这是我目前的工作进度代码,用于检测的监测设备id、可靠。
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++;
}
其他提示
我刚刚发现了你可以查询Win32_PnPEntity服务="监视器",它将返回的所有监视器。
结果我的机器:
select * from Win32_PnPEntity where service="monitor"
Availability | Caption | ClassGuid | CompatibleID | ConfigManagerErrorCode | ConfigManagerUserConfig | CreationClassName | Description | DeviceID | ErrorCleared | ErrorDescription | HardwareID | InstallDate | LastErrorCode | Manufacturer | Name | PNPDeviceID | PowerManagementCapabilities | PowerManagementSupported | Service | Status | StatusInfo | SystemCreationClassName | SystemName
| Dell 2007FP (Digital) | {4d36e96e-e325-11ce-bfc1-08002be10318} | array[0..0] | 0 | False | Win32_PnPEntity | Dell 2007FP (Digital) | DISPLAY\DELA021\5&4F61016&0&UID257 | | | array[0..0] | | | Dell Inc. | Dell 2007FP (Digital) | DISPLAY\DELA021\5&4F61016&0&UID257 | | | monitor | OK | | Win32_ComputerSystem | 8HVS05J
| Dell ST2320L_Digital | {4d36e96e-e325-11ce-bfc1-08002be10318} | array[0..0] | 0 | False | Win32_PnPEntity | Dell ST2320L_Digital | DISPLAY\DELF023\5&4F61016&0&UID256 | | | array[0..0] | | | Dell Inc. | Dell ST2320L_Digital | DISPLAY\DELF023\5&4F61016&0&UID256 | | | monitor | OK | | Win32_ComputerSystem | 8HVS05J
我们一直在玩弄EnumDisplayDevices为了检测,如果目前的视频卡制造商的独.这是不一样的,但也许它会帮助。我们一块看起来是这样的:
int disp_num = 0;
BOOL res = TRUE;
do {
DISPLAY_DEVICE disp_dev_info;
ZeroMemory( &disp_dev_info, sizeof(DISPLAY_DEVICE) );
disp_dev_info.cb = sizeof(DISPLAY_DEVICE);
res = EnumDisplayDevices( 0, disp_num++, &disp_dev_info, 0x00000001 );
if(res &&
disp_dev_info.DeviceString[0]!=0 && disp_dev_info.DeviceString[0]=='N' &&
disp_dev_info.DeviceString[1]!=0 && disp_dev_info.DeviceString[1]=='V' &&
disp_dev_info.DeviceString[2]!=0 && disp_dev_info.DeviceString[2]=='I' &&
disp_dev_info.DeviceString[3]!=0 && disp_dev_info.DeviceString[3]=='D' &&
disp_dev_info.DeviceString[4]!=0 && disp_dev_info.DeviceString[4]=='I' &&
disp_dev_info.DeviceString[5]!=0 && disp_dev_info.DeviceString[5]=='A'){
isNVidia = true;
}
int x = 0;
}while( res != FALSE );
非常愚蠢,但工作。
我从来没有试过这样做,从一个服务,但是 EnumDisplayDevices
一般运作良好时,运作一个用户。我认为,服务的运行在一个独立(和无头)会议,这可以解释的问题你看到那里。
你能不能运行的一个辅助程序,从您的服务,冒充一个用户账户,有权访问所显示?
该Win32_DesktopMonitor方法只有1返回监视器在我Vista机。PnP ID似乎可以设置正确,虽然。
我有一个快速发挥EnumDisplayDevices API,同时它似乎发现适配的详细信息可靠地(大概是因为大多数人不会离开它,因为"标准VGA"长期),只有返回"插播放监视器"的连接监视。
这反映出研究,我有没有进入这几年前(不得不把一些代码在一起,以帮助在撒那些记忆断)。
这是一个正常的用户账户。如果你已经有了一个可靠的方式获得EnumDisplayDevices返回PnP ID,即使在正常的用户会议,我会很感兴趣--我们目前正在调查如果任何这种信息可用设备司机。
有一件事你能做的,如果运行的代码届会议#0是不够可靠,看看如果你可以产生一个辅助程序(无论是使用CreateProcessAsUser或使用COM与激活的绰号),将运行在用户的背景。