2008-10-08 11 views
9

Para mi proyecto actual de C++, necesito detectar una cadena única para cada monitor que esté conectado y activo en una gran cantidad de computadoras.EnumDisplayDevices vs WMI Win32_DesktopMonitor, ¿cómo detectar monitores activos?

La investigación ha señalado a 2 opciones

  1. utilizar WMI y consultar el Win32_DesktopMonitor para todos los monitores activos. Use PNPDeviceID para la identificación única de monitores.

  2. Utilice la API EnumDisplayDevices y cave para obtener la ID del dispositivo.

Estoy interesado en utilizar el ID de dispositivo para la identificación del modelo único porque los monitores usando el enchufe del defecto y jugar conductor reportará una cadena genérica como el nombre del monitor "enchufe del defecto monitor de reproducción"

I he tenido problemas con el método WMI, parece que solo estoy devolviendo 1 monitor en mi máquina Vista, mirando al doco resulta que no funciona como se esperaba en dispositivos que no son WDDM.

EnumDisplayDevices parece ser un poco problemático para ponerse en marcha cuando se ejecuta desde un servicio en segundo plano (especialmente en Vista), si está en la sesión 0 no devolverá información.

  • Alguien más tenía que hacer algo similar (Encontrar cadena modelo único para todos los monitores activos conectados?)

  • Qué enfoque funcionó mejor?

Respuesta

10

Este es mi código actual de trabajo en progreso para detectar la identificación del dispositivo del monitor, de manera confiable.

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++; 
} 
+0

Intenté implementar tu código. Estoy obteniendo un identificador de error 'DeviceID no está definido' Intenté buscar en msdn un include apropiado sin embargo no pude encontrar ningún parámetro DeviceID separado. ¿Puede decirme qué archivo de encabezado debo incluir para identificar DeviceID? – newbie2015

0

nunca he intentado hacerlo desde un servicio, pero EnumDisplayDevices normalmente funciona bien cuando se ejecuta como un usuario. Creo que los servicios se ejecutan en una sesión separada (y sin cabeza), lo que podría explicar el problema que está viendo allí.

¿Podría ejecutar un programa auxiliar de su servicio, suplantando una cuenta de usuario que tiene acceso a las pantallas?

1

Hemos estado jugando con EnumDisplayDevices para detectar si el fabricante actual de la tarjeta de video es NVIDIA. No es lo mismo, pero tal vez ayudaría. Nuestra pieza se veía así:

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); 

Bastante tonto, pero trabajando.

+0

Una cosa que es crítica y que falta de esta muestra es la ignorancia de los dispositivos de espejo y sólo mirar a los dispositivos activos. Ver http://msdn.microsoft.com/en-us/library/aa477606.aspx. Publicaré mi muestra de trabajo actual. –

0

El método Win32_DesktopMonitor solo devuelve 1 monitor en mi máquina Vista también. Sin embargo, el ID de PnP parece estar configurado correctamente.

He tenido un juego rápido con la API EnumDisplayDevices, y aunque parece descubrir los detalles del adaptador de manera confiable (presumiblemente porque la mayoría de las personas no lo dejarán como "VGA estándar" por mucho tiempo), solo devuelve "Plug" y Play Monitor "para los monitores conectados.

Esto hace eco de la investigación que hice en esto hace varios años (tuve que poner algunos códigos juntos para ayudar a desempolvar esos recuerdos).

Esto es de una cuenta de usuario normal. Si tiene una forma confiable de que EnumDisplayDevices devuelva la ID de PnP, incluso en las sesiones de usuario normales, me interesaría: actualmente estamos investigando si alguna parte de esta información está disponible para un controlador de dispositivo.

Una cosa que podría hacer, si ejecutar el código de la sesión # 0 no es lo suficientemente confiable, es ver si puede generar un proceso de ayuda (ya sea usando CreateProcessAsUser o COM con monikers de activación) que se ejecutará el contexto del usuario.

+0

Yerp, CreateProcessAsUser funciona bien, lo probamos el otro día. Introduce bastante complejidad pero parece ser la única forma de obtener esa información de manera confiable –

2

Acabo de descubrir puede consultar Win32_PnPEntity para el servicio = "monitor", y ha de devolver todos los monitores.

Resultados en mi máquina:

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 
+1

Esto simplemente me da "Genérico PnP Monitor" para todos los monitores – acron

Cuestiones relacionadas