2008-10-08 167 views
9

對於我當前的C++項目,我需要爲大量計算機上連接並激活的每個監視器檢測唯一的字符串。EnumDisplayDevices與WMI Win32_DesktopMonitor,如何檢測活動監視器?

有研究指出,2個選項

  1. 使用WMI和查詢Win32_DesktopMonitor所有活動監視器。使用PNPDeviceID進行顯示器的唯一標識。

  2. 使用EnumDisplayDevices API,並挖掘以獲取設備ID。

我很感興趣,因爲使用顯示器默認的即插即用驅動程序會報告一個通用的字符串作爲顯示器命名爲「默認即插即用監視器」

我用獨特的模型識別的設備ID一直在遇到WMI方法的問題,它似乎只在我的Vista機器上返回1臺顯示器,看着doco,結果表明它在非WDDM設備上無法正常工作。

EnumDisplayDevices在從後臺服務運行時(特別是在Vista上)似乎有點問題,如果它在會話0中,它將不返回任何信息。

  • 任何人都有做類似的事情(找到所有連接的有源監聽音箱獨特的模式字符串?)

  • 哪種方法最有效?

回答

10

這是我目前正在工作的代碼,用於可靠地檢測監視器設備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++; 
} 
+0

我試着實現您的代碼。我得到一個錯誤`標識符DeviceID是未定義的`我試圖在MSDN上搜索適當的包括但是我找不到任何單獨的DeviceID參數。你能告訴我什麼頭文件,我包括DeviceID來識別。 – newbie2015 2015-10-01 09:58:23

0

我從來沒有嘗試過從服務中做到這點,但EnumDisplayDevices作爲用戶運行時一般效果很好。我相信服務在單獨的(無頭的)會話中運行,這可以解釋您在那裏看到的問題。

您可以從您的服務運行幫助程序,模擬有權訪問顯示器的用戶帳戶嗎?

1

我們一直在玩EnumDisplayDevices以檢測當前的視頻卡製造商是否爲NVIDIA。這是不一樣的,但也許會有所幫助。我們的作品看起來像這樣:

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

很笨,但工作。

+0

有一點是至關重要的,並從這個樣本缺少的是鏡設備的忽視,只看着有源器件。請參閱http://msdn.microsoft.com/en-us/library/aa477606.aspx。將發佈我目前的工作示例。 – 2008-10-14 21:10:40

0

Win32_DesktopMonitor方法也只在我的Vista機器上返回1個顯示器。雖然,PnP ID似乎設置正確。

我已經快速玩過EnumDisplayDevices API,雖然它似乎可靠地發現適配器的細節(大概是因爲大多數人不會把它作爲「標準VGA」長),它只返回「Plug和「播放監視器」。

這與我幾年前做過的研究(必須將一些代碼放在一起以幫助清除那些記憶)相呼應。

這是來自一個普通的用戶帳戶。如果你有一個可靠的方法讓EnumDisplayDevices返回PnP ID,即使在正常的用戶會話中,我也會感興趣 - 我們目前正在研究是否有任何這些信息可用於設備驅動程序。

你可以做的一件事是,如果從會話#0運行代碼不夠可靠,那就是看你是否可以產生一個輔助進程(使用CreateProcessAsUser或使用COM與激活標記)來運行用戶的上下文。

+0

Yerp,CreateProcessAsUser正常工作,我們測試了那一天。它確實引入了相當多的複雜性,但似乎是唯一能夠可靠地獲取該信息的方法。 – 2008-10-14 21:03:46

2

我剛剛發現你可以查詢Win32_PnPEntity的service =「monitor」,它會返回所有的監視器。

結果我的機器上:

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

這只是給我所有顯示器的「通用即插即用顯示器」 – acron 2012-06-21 10:37:30