Domanda

Per il mio attuale progetto C ++ ho bisogno di rilevare una stringa univoca per ogni monitor collegato e attivo su un gran numero di computer.

La ricerca ha indicato 2 opzioni

  1. Usa WMI e interroga Win32_DesktopMonitor per tutti i monitor attivi. Utilizzare PNPDeviceID per l'identificazione univoca dei monitor.

  2. Utilizza l'API EnumDisplayDevices e scendi per ottenere l'ID del dispositivo.

Sono interessato a utilizzare l'ID del dispositivo per l'identificazione univoca del modello perché i monitor che utilizzano il driver plug and play predefinito segnaleranno una stringa generica come nome monitor "monitor plug and play predefinito";

Ho riscontrato problemi con il metodo WMI, sembra che stia restituendo solo 1 monitor sulla mia macchina Vista, guardando il documento risulta che non funziona come previsto su dispositivi non WDDM.

EnumDisplayDevices sembra essere un po 'problematico per iniziare quando viene eseguito da un servizio in background (specialmente su Vista), se è nella sessione 0 non restituirà informazioni.

  • Qualcun altro ha dovuto fare qualcosa di simile (trovare una stringa di modello univoca per tutti i monitor attivi collegati?)

  • Quale approccio ha funzionato meglio?

È stato utile?

Soluzione

Questo è il mio attuale codice di work-in-progress per rilevare in modo affidabile l'ID del dispositivo di monitoraggio.

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

Altri suggerimenti

Ho appena scoperto che puoi eseguire una query su Win32_PnPEntity per service = " monitor " ;, e restituirà tutti i monitor.

Risultati sul mio computer:

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

Abbiamo giocato con EnumDisplayDevices per rilevare se l'attuale produttore della scheda video è NVIDIA. Non è lo stesso, ma forse sarebbe d'aiuto. Il nostro pezzo sembrava così:

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

Abbastanza stupido, ma funzionante.

Non ho mai provato a farlo da un servizio, ma EnumDisplayDevices generalmente funziona bene quando eseguito come utente. Credo che i servizi funzionino in una sessione separata (e senza testa), il che potrebbe spiegare il problema che stai vedendo lì.

Potresti eseguire un programma di supporto dal tuo servizio, impersonando un account utente che ha accesso ai display?

Il metodo Win32_DesktopMonitor restituisce solo 1 monitor anche sul mio computer Vista. L'ID PnP sembra essere impostato correttamente, tuttavia.

Ho avuto un gioco veloce con l'API EnumDisplayDevices e, sebbene sembri scoprire i dettagli dell'adattatore in modo affidabile (presumibilmente perché la maggior parte delle persone non lo lascerà come "VGA standard" a lungo), restituisce solo " Plug and Play Monitor " per i monitor collegati.

Questo fa eco alla ricerca che ho fatto in questo diversi anni fa (ho dovuto mettere insieme un po 'di codice per aiutare a rispolverare quei ricordi).

Questo proviene da un normale account utente. Se hai un modo affidabile per ottenere EnumDisplayDevices per restituire l'ID PnP, anche nelle normali sessioni utente, sarei interessato - stiamo attualmente esaminando se una di queste informazioni è disponibile per un driver di dispositivo.

Una cosa che potresti fare, se eseguire il codice dalla sessione # 0 non è abbastanza affidabile, è vedere se puoi generare un processo di supporto (usando CreateProcessAsUser o usando COM con i moniker di attivazione) che verrà eseguito nel contesto dell'utente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top