1

I am building a simple program that when it is ran it will show different computer components.

Right now I am trying to show all monitors plugged in. The name of each and the total amount plugged into the computer.

When I run the below code, It only shows me the name of one monitor even though I am plugged into three. Could someone please tell me why.

public static List<string> GetMonitorNames()
{
    ManagementClass mc = new ManagementClass("Win32_DesktopMonitor");
    ManagementObjectCollection moc = mc.GetInstances();
    var info = new List<string>();
    foreach (ManagementObject mo in moc)
    {
        info.Add(mo["Name"].ToString());
    }
    return info;
}
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
KevinM1990112qwq
  • 715
  • 2
  • 10
  • 23

2 Answers2

2

You can get the instance names of all monitiors using the WmiMonitorBasicDisplayParams method.

Here is an example

public static List<string> GetMonitorNames()
{
    ManagementObjectSearcher searcher =
            new ManagementObjectSearcher("root\\WMI",
            "SELECT * FROM WmiMonitorBasicDisplayParams");
    var info = new List<string>();
    foreach (ManagementObject queryObj in searcher.Get()) { 
        info.Add(queryObj["InstanceName"].ToString());
    }
    return info;
}

Example output from my machine and available properties on this object

Active                        : True
DisplayTransferCharacteristic : 120
InstanceName                  : DISPLAY\HWP3270\4&7563392&0&UID16843008_0
MaxHorizontalImageSize        : 52
MaxVerticalImageSize          : 32
SupportedDisplayFeatures      : WmiMonitorSupportedDisplayFeatures
VideoInputType                : 0
PSComputerName                :

Active                        : True
DisplayTransferCharacteristic : 120
InstanceName                  : DISPLAY\HWP326E\4&7563392&0&UID53349120_0
MaxHorizontalImageSize        : 52
MaxVerticalImageSize          : 32
SupportedDisplayFeatures      : WmiMonitorSupportedDisplayFeatures
VideoInputType                : 1
PSComputerName                :
hawkstrider
  • 4,141
  • 16
  • 27
  • I see what you did there, but there are *many* google results for WMI only returning one instance. Are you sure this works? – Robert Harvey May 20 '16 at 17:00
  • I did not do any checking on his code and getting monitor information, merely showing that if he is iterating a collection, to get all he will need to use a collection and not overwrite the value each time – hawkstrider May 20 '16 at 17:03
  • When I use this I get cannot convert type System.collections.Generic.List to string. That error happens on this code `lblMon.Text = HardwareInfo.GetMonitorNames();` – KevinM1990112qwq May 20 '16 at 17:05
  • You can't set a list of string to a string property. If you want to set it to a string, you will need to concatenate them together. – hawkstrider May 20 '16 at 17:06
  • Negative. Did not work on my machine (it only returned the *first* monitor). – Robert Harvey May 20 '16 at 17:07
  • @bhmahler I followed the edit, it still only shows the first monitor though. – KevinM1990112qwq May 20 '16 at 17:10
  • It appears that @RobertHarvey is correct. The iteration was not the root problem – hawkstrider May 20 '16 at 17:10
  • 1
    I moved your fixed code into the question, since the list iteration is not germane to the problem. Feel free to post a solution to that. – Robert Harvey May 20 '16 at 17:14
  • @RobertHarvey Will do, if I ever get it figured out. haha. – KevinM1990112qwq May 20 '16 at 17:17
  • @bhmahler That way works and shows them, It does not have classes for showing the names of the monitors though. For instance, Surface display, Pavilion 23xi and so fourth. I've ran through them all from the google docs on it. Also, is there a way I can print out just a number of active displays? like 1-2-3 and so fourth? – KevinM1990112qwq May 20 '16 at 17:44
  • @bhmahler I have also tried WmiMonitorID and using the query object UserFriendlyName, Which breaks my code. even though it is a class on the docs. When I use WmiMonitorID and instanceName though. Gives me the same thing again. – KevinM1990112qwq May 20 '16 at 17:49
  • @bhmahler I was getting ym info from here https://msdn.microsoft.com/en-us/library/windows/desktop/aa394542(v=vs.85).aspx all of the members of that class are working aside from the userfriendlyname which I believe is what I want. – KevinM1990112qwq May 20 '16 at 17:51
  • @bhmahler I guess its breaking on a null exception which makes no sense because it should not be null. – KevinM1990112qwq May 20 '16 at 17:56
2

Not a direct answer to the question as posed, but rather than deferring to WMI, why not use a solution available to you in .net, like this Winforms solution:

using System.Diagnostics;
using System.Windows.Forms;

Debug.Print("Total Number Of Monitors: {0}", Screen.AllScreens.Length);
foreach (Screen scr in Screen.AllScreens)
{
    Debug.Print(scr.DeviceName);
}

To clarify based on your comment, yes the method can be used from within a static method, as in:

public static List<string> GetAllMonitorNames()
{
    List<string> result = new List<string>();
    foreach (Screen scr in Screen.AllScreens)
    {
        result.Add(scr.DeviceName);
    }
    return result;
}

or using LINQ if you prefer:

public static IEnumerable<string> GetAllMonitorNames() => 
            Screen.AllScreens.Select((s) => s.DeviceName);

You can also still just P/Invoke the API's EnumDisplayMonitors, and add the display names to the list. (pinvoke.net example)

theB
  • 6,450
  • 1
  • 28
  • 38
  • Again, I am fairly new to this. Can I change this code to put it into my public static GetMonitorNames();? So I can call it from a label? – KevinM1990112qwq May 20 '16 at 17:22
  • @KevinM1990112qwq: You'll need to shore up your knowledge about how to work with collections and strings, sport. bhmahler already showed you how to do that in his answer. – Robert Harvey May 20 '16 at 17:24
  • So adding this answer would work the same way as BH showed me? Sorry, and thank you for the response. – KevinM1990112qwq May 20 '16 at 17:26
  • Yes, but like @RobertHarvey said, you probably want to brush up on working with collections. [MSDN](https://msdn.microsoft.com/en-us/library/mt654013.aspx) has a good article, or if the dead-tree route works for you Jon Skeet's C# in Depth, or Eric Lippert's Essential C# are very good. – theB May 20 '16 at 17:54
  • @theB How can I get the actual names? when I run it just says \\.\Display1,\\.\Display2\ – KevinM1990112qwq May 20 '16 at 17:59
  • Those are the actual names. If you're looking for a name like "DELL P2714H" that's the friendly name, and its a bit more complicated. [Quite a bit](http://stackoverflow.com/questions/4958683/how-do-i-get-the-actual-monitor-name-as-seen-in-the-resolution-dialog) – theB May 20 '16 at 18:22
  • That is exactly what I'm looking for. The friendly name – KevinM1990112qwq May 20 '16 at 18:40
  • @theB Alright, I followed the link you just posted and got it all working. One last issue. It is displaying the friend;ly name now for my 27xi Pavilion. My surface screen however, It is just blank. – KevinM1990112qwq May 20 '16 at 18:47
  • @theB And how can I just display one line that says, Number of active display : 3 – KevinM1990112qwq May 20 '16 at 18:48
  • @theB Are you able to check this out? – KevinM1990112qwq May 20 '16 at 19:35
  • @KevinM19900112qwq - Just peek at the first block of code in the answer before the foreach loop, the count is right there. – theB May 20 '16 at 20:16