2013-09-16 38 views
1

我遇到了一個在C#中使用EnumDisplayDevices的問題。我使用了代碼here,它可以無縫工作。但是最近我轉而在我的臺式電腦上編寫應用程序。代碼不再有效,不給我任何東西。EnumDisplayDevices不返回任何東西

如果有幫助,我的顯示器是在AMD的Radeon HD 5770

這裏運行的LG W2753VC是我當前的代碼:

 var device = new DISPLAY_DEVICE(); 

     device.cb = Marshal.SizeOf(device); 
     try { 
      for (uint id = 0; EnumDisplayDevices(null, id, ref device, 0); id++) { 
       device.cb = Marshal.SizeOf(device); 
       EnumDisplayDevices(device.DeviceName, 0, ref device, 0); 
       device.cb = Marshal.SizeOf(device); 

       Console.WriteLine("id={0}, name={1}, devicestring={2}", id, device.DeviceName, device.DeviceString); 
       if (device.DeviceName == null || device.DeviceName == "") continue; 
      } 
     } catch (Exception ex) { } 

我得到我的筆記本電腦是什麼:

id=0, name=\\.\DISPLAY1\Monitor0, devicestring=Generic PnP Monitor 

(這應該是「移動PC顯示器」,但在這裏不是問題)

我是什麼在我的桌面上:

id=0, name=, devicestring= 
id=1, name=, devicestring= 

我做錯了,如果沒有,是否有任何其他方式來獲得所有連接的顯示器?我已經嘗試過WMI和註冊表方法。

回答

6

很難說,沒有你發佈你所有的p/invoke代碼。這裏的代碼,我的工作站上的工作原理:

public class EnumDisplayDevicesTest 
{ 
    [DllImport("user32.dll")] 
    static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags); 

    [Flags()] 
    public enum DisplayDeviceStateFlags : int 
    { 
     /// <summary>The device is part of the desktop.</summary> 
     AttachedToDesktop = 0x1, 
     MultiDriver = 0x2, 
     /// <summary>The device is part of the desktop.</summary> 
     PrimaryDevice = 0x4, 
     /// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary> 
     MirroringDriver = 0x8, 
     /// <summary>The device is VGA compatible.</summary> 
     VGACompatible = 0x10, 
     /// <summary>The device is removable; it cannot be the primary display.</summary> 
     Removable = 0x20, 
     /// <summary>The device has more display modes than its output devices support.</summary> 
     ModesPruned = 0x8000000, 
     Remote = 0x4000000, 
     Disconnect = 0x2000000 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
    public struct DISPLAY_DEVICE 
    { 
     [MarshalAs(UnmanagedType.U4)] 
     public int cb; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
     public string DeviceName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceString; 
     [MarshalAs(UnmanagedType.U4)] 
     public DisplayDeviceStateFlags StateFlags; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceID; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 
     public string DeviceKey; 
    } 

    public void Display() 
    { 
     DISPLAY_DEVICE d = new DISPLAY_DEVICE(); 
     d.cb = Marshal.SizeOf(d); 
     try 
     { 
      for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++) 
      { 
       if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop)) 
       { 
        Console.WriteLine(
         String.Format("{0}, {1}, {2}, {3}, {4}, {5}", 
           id, 
           d.DeviceName, 
           d.DeviceString, 
           d.StateFlags, 
           d.DeviceID, 
           d.DeviceKey 
           ) 
           ); 
        d.cb = Marshal.SizeOf(d); 
        EnumDisplayDevices(d.DeviceName, 0, ref d, 0); 
        Console.WriteLine(
         String.Format("{0}, {1}", 
           d.DeviceName, 
           d.DeviceString 
           ) 
           ); 
       } 
       d.cb = Marshal.SizeOf(d); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(String.Format("{0}", ex.ToString())); 
     } 
    } 
} 

上面的代碼工作作爲OP希望在我的機器,不知道爲什麼它不會在他的筆記本電腦工作。

的替代方法得到的信息在下面列出,取自here

foreach (var display in DisplayDetails.GetMonitorDetails()) 
{ 
    Console.WriteLine(display.Model); 
} 

public class DisplayDetails 
{ 
    public string PnPID { get; set; } 

    public string SerialNumber { get; set; } 

    public string Model { get; set; } 

    public string MonitorID { get; set; } 

    /// <summary> 
    /// The Constructor to create a new instances of the DisplayDetails class... 
    /// </summary> 
    public DisplayDetails(string sPnPID, string sSerialNumber, string sModel, string sMonitorID) 
    { 
     PnPID = sPnPID; 
     SerialNumber = sSerialNumber; 
     Model = sModel; 
     MonitorID = sMonitorID; 
    } 

    /// <summary> 
    /// This Function returns all Monitor Details 
    /// </summary> 
    /// <returns></returns> 
    static public IEnumerable<DisplayDetails> GetMonitorDetails() 
    { 
     //Open the Display Reg-Key 
     RegistryKey Display = Registry.LocalMachine; 
     Boolean bFailed = false; 
     try 
     { 
      Display = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\DISPLAY"); 
     } 
     catch 
     { 
      bFailed = true; 
     } 

     if (!bFailed & (Display != null)) 
     { 

      //Get all MonitorIDss 
      foreach (string sMonitorID in Display.GetSubKeyNames()) 
      { 
       RegistryKey MonitorID = Display.OpenSubKey(sMonitorID); 

       if (MonitorID != null) 
       { 
        //Get all Plug&Play ID's 
        foreach (string sPNPID in MonitorID.GetSubKeyNames()) 
        { 
         RegistryKey PnPID = MonitorID.OpenSubKey(sPNPID); 
         if (PnPID != null) 
         { 
          string[] sSubkeys = PnPID.GetSubKeyNames(); 

          //Check if Monitor is active 
          if (sSubkeys.Contains("Control")) 
          { 
           if (sSubkeys.Contains("Device Parameters")) 
           { 
            RegistryKey DevParam = PnPID.OpenSubKey("Device Parameters"); 
            string sSerial = ""; 
            string sModel = ""; 

            //Define Search Keys 
            string sSerFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xff }); 
            string sModFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xfc }); 

            //Get the EDID code 
            byte[] bObj = DevParam.GetValue("EDID", null) as byte[]; 
            if (bObj != null) 
            { 
             //Get the 4 Vesa descriptor blocks 
             string[] sDescriptor = new string[4]; 
             sDescriptor[0] = Encoding.Default.GetString(bObj, 0x36, 18); 
             sDescriptor[1] = Encoding.Default.GetString(bObj, 0x48, 18); 
             sDescriptor[2] = Encoding.Default.GetString(bObj, 0x5A, 18); 
             sDescriptor[3] = Encoding.Default.GetString(bObj, 0x6C, 18); 

             //Search the Keys 
             foreach (string sDesc in sDescriptor) 
             { 
              if (sDesc.Contains(sSerFind)) 
              { 
               sSerial = sDesc.Substring(4).Replace("\0", "").Trim(); 
              } 
              if (sDesc.Contains(sModFind)) 
              { 
               sModel = sDesc.Substring(4).Replace("\0", "").Trim(); 
              } 
             } 


            } 
            if (!string.IsNullOrEmpty(sPNPID + sSerFind + sModel + sMonitorID)) 
            { 
             yield return new DisplayDetails(sPNPID, sSerial, sModel, sMonitorID); 
            } 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
+0

這似乎讓顯卡連接到我的電腦。我如何從中獲得顯示器?我試着對'EnumDisplayDevices'進行第二次調用,但同樣的問題依然存在。 – pbondoer

+1

確保您只查看連接到桌面的設備(DisplayDeviceStateFlags.AttachedToDesktop)。看到上面編輯的代碼。 – GalacticJello

+0

還是不行。它首先顯示圖形卡(如預期的那樣),然後顯示','。看起來對象中的所有字符串都是空的:( – pbondoer

0

我有完全相同這種行爲時device.cb(分別sizeofDISPLAY_DEVICEWDISPLAY_DEVICEA)不等於840的一個或224 。在我的情況,我只是錯誤地寫了device.cb = sizeof(device.cb); 在兩臺計算機上檢查值爲Marshal.SizeOf(device)

0

GalacticJello的代碼示例正在爲我工​​作。我強制構​​建x86的程序集。

在其他情況下也許嘗試: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct DISPLAY_DEVICE`

但這不是工作86!