1

In Windows we have information about our Monitros - some unique name and id. e.g.

  1. Acer xxx
  2. Samsung xxx

I have qeuestion how to get the information in C#, because I know that serial number we can get from WMI: root\WMI -> WmiMonitorID

and about displays: root/CIMV2 Win32_DesktopMonitor

But I have to have this infromation together, it meens Aceer S/N xxx have id 1 in Windows

Have anybody some idea?

jeremmy
  • 11
  • 1
  • 1
  • 2

4 Answers4

4

Give this a shot:

using System.Management;

ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_DesktopMonitor");     
foreach (ManagementObject obj in searcher.Get())
    Console.WriteLine("Description: {0}", obj ["Description"]);

EDIT:

And here's a link to a nice looking class that will retrieve the monitor details:

http://wmimonitor.svn.sourceforge.net/viewvc/wmimonitor/DisplayInfoWMIProvider/WMIProvider/WMIProvider.cs?view=markup

Here is the class associated with the above link. It should give you everything you need about the monitor:

//DisplayInfoWMIProvider (c) 2009 by Roger Zander

using System;
using System.Collections;
using System.Management.Instrumentation;
using System.DirectoryServices;
using System.Management;
//using System.Security.Principal;
using Microsoft.Win32;
using System.Text;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;            

[assembly: WmiConfiguration(@"root\cimv2", HostingModel = ManagementHostingModel.LocalSystem)]
namespace DisplayInfoWMIProvider
{
    [System.ComponentModel.RunInstaller(true)]
    public class MyInstall : DefaultManagementInstaller
    {
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            System.Runtime.InteropServices.RegistrationServices RS = new System.Runtime.InteropServices.RegistrationServices();

            //This should be fixed with .NET 3.5 SP1
            //RS.RegisterAssembly(System.Reflection.Assembly.LoadFile(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\v3.5\System.Management.Instrumentation.dll")), System.Runtime.InteropServices.AssemblyRegistrationFlags.SetCodeBase);
        }

        public override void Uninstall(IDictionary savedState)
        {

            try
            {
                ManagementClass MC = new ManagementClass(@"root\cimv2:Win32_MonitorDetails");
                MC.Delete();
            }
            catch { }

            try
            {
                base.Uninstall(savedState);
            }
            catch { }
        }
    }

    [ManagementEntity(Name = "Win32_MonitorDetails")]
    public class DisplayDetails
    {
        [ManagementKey]
        public string PnPID { get; set; }

        [ManagementProbe]
        public string SerialNumber { get; set; }

        [ManagementProbe]
        public string Model { get; set; }

        [ManagementProbe]
        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>
        [ManagementEnumerator]
        static public IEnumerable 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);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
James Johnson
  • 45,496
  • 8
  • 73
  • 110
  • Thank for a reply, unfortunatelly description is not unique name, because I have this kind of Reuslts (I have two monitors): Default Monitor, Default Monitor, Generic PnP Monitor – jeremmy Sep 01 '11 at 14:25
  • Code from this link give a information about SerialNumber and other details, but not give me information what is ther order of the monitors in Windows: first monitor, second... – jeremmy Sep 01 '11 at 14:31
  • @jeremmy: You don't have to use Description. Replace that with whatever field you want - Serial Number, etc. Also, see edited answer with link to class. – James Johnson Sep 01 '11 at 14:34
  • Yes, I know that I have information about SerialNumber, but unfortunatelly we don't know id of the monitors. E.G. we 2 monitors with Serial Number S/N: A, S/N: B, using above code I have this information, but I don't know if S/N: A is first or second monitor (the order in SYSTEM\CurrentControlSet\Enum\DISPLAY is not the same with orders in Windows). But maybe I wrong undarstand you? – jeremmy Sep 01 '11 at 14:47
  • @jeremmy: Did you try the second solution? The class I posted in my updated answer? Is there no way to retrieve the information you need from this class? – James Johnson Sep 01 '11 at 14:51
  • Yes, I was trying it, and unfortunatelly the order of the monitors is not the same like in Windows and MonitorID it is not some intger value but string, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\SAM01BB. Maybe I will explain my problem from other side: we have 3 monitors, we know some unique name of them, e.g. Serial Number: S/n: A, S/N: B, S/N: C. Now I would show some picture on monitor with S/N: B, how I could it doing? – jeremmy Sep 02 '11 at 07:09
  • Nice solution - thanks for unearthing it. I noticed in testing this fragment that it will report on any displays that have been used in the current session, e.g. a projector connected and disconnected will still be reported until the system is rebooted. – holtavolt Apr 03 '12 at 16:43
1

root/CIMV2/Win32_DesktopMonitor/PnPDeviceID only show 2 of my 5 monitors and root/WMI/WMIMonitorId/InstanceName shows all 5 of my monitors

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\WMI") 
Set colItems = objWMIService.ExecQuery( _
    "SELECT * FROM WmiMonitorID",,48) 
For Each objItem in colItems 
    Wscript.Echo "-----------------------------------"
    Wscript.Echo "WmiMonitorID instance"
    Wscript.Echo "-----------------------------------"
    Wscript.Echo "InstanceName: " & objItem.InstanceName
Next
-1

As an example, we use this to retrieve the serial from the primary HDD using WMI:

var search = new ManagementObjectSearcher("select * from Win32_LogicalDisk where DeviceID = 'C:'");
var serials = search.Get().OfType<ManagementObject>();
m_clientToken = serials.ElementAt(0)["VolumeSerialNumber"].ToString();

Perhaps you can utilize this to get your monitor information since you know which Mgmt Object to search. You basically use SQL to retrieve what you're looking for.

Matt Thomas
  • 463
  • 3
  • 9
  • Thanks for a reply. I know how to get the serialnumber information, but the problem is how to get this information: we have 3 monitors: S/N: xxx, S/N: yyy, S/N: zzz and I wolud like to now what is the id of this monitors, which monitor is first in Windows, second... – jeremmy Sep 01 '11 at 13:10
-1

It seems to me that root/CIMV2/Win32_DesktopMonitor/PnPDeviceID (1) and root/WMI/WMIMonitorId/InstanceName (2) are nearly identical

I found the following on my computer using WMI Explorer

(1) DISPLAY\HWP2868\5&3EB7FBC&0&UID16777472

(2) DISPLAY\HWP2868\5&3eb7fbc&0&UID16777472_0

There are two differences: the _0 at the end of (2) and the fact that parts of (2) is lower case.

I do not have more than a single monitor for reference at the moment, therefore I can not provide you with a more accurate way to associate the two entries. But it looks to me like you could write two queries, modifying the search condition in one of them to match the other's format. But you need to investigate whether or not there is a reliable pattern to do so.

At any rate, there seems to be enough common elements to be able to make a match in code, if not by query.

havardhu
  • 3,576
  • 2
  • 30
  • 42
  • What is strange, I have two monitors, but in root/CIMV2/Win32_DesktopMonitor I have fill only PnPDeviceID for second monitor. – jeremmy Sep 01 '11 at 13:55