1

I would like to know how to add item to the dictionary from the first foreach loop and the second foreach loop at the same time..

For example - the first loop adds the first contents to the item and starts the second loop which I want it to add the first item in the loop and then starts the outside loop without reading the second item. Do the same and add the second item from the second loop.

Sorry if the question is confusing..Weak english.

List<object> items = new List<object>();
DeviceSettings deviceSettings = new DeviceSettings();
List<object> deviceName = deviceSettings.GetMonitorFriendlyName();

using (ManagementObjectCollection moc = searcher.Get())
{  
    foreach (ManagementObject mo in moc)
    {
        Dictionary<string, object> item = new Dictionary<string, object>();
        ConnectedMonitor_Number = searcher.Get().Count;

        item.Add("DefaultMonitorLength", DefaultMonitor_Width);
        item.Add("DefaultMonitorHeight", DefaultMonitor_Height);
        item.Add("ConnectedMonitor_Numb", Convert.ToString(ConnectedMonitor_Number));
        item.Add("Caption", Convert.ToString(mo["Caption"]));
        item.Add("Name", Convert.ToString(mo["Name"]));
        item.Add("Description", Convert.ToString(mo["Description"]));
        item.Add("DeviceID", Convert.ToString(mo["DeviceID"]));
        item.Add("Manufacturer", Convert.ToString(mo["Manufacturer"]));
        string[] HardwareID = (string[])mo["HardwareID"];
        item.Add("HardwareID", string.Join(";", HardwareID));
        item.Add("Status", Convert.ToString(mo["Status"]));

        foreach (Dictionary<string, string> dm in deviceName)
        {
            item["monitorname"] = Convert.ToString(dm["monitorname"]);
        }

        items.Add(item);
    }
}

---This is the devicesettings.cs ---

public static string MonitorFriendlyName(LUID adapterId, uint targetId)
    {
        DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME();
        deviceName.header.size = (uint)Marshal.SizeOf(typeof(DISPLAYCONFIG_TARGET_DEVICE_NAME));
        deviceName.header.adapterId = adapterId;
        deviceName.header.id = targetId;
        deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
        int error = DisplayConfigGetDeviceInfo(ref deviceName);
        if (error != ERROR_SUCCESS)
            throw new Win32Exception(error);
        return deviceName.monitorFriendlyDeviceName;
    }

    public List<object> GetMonitorFriendlyName()
    {
        try
        {
            List<object> items = new List<object>();
            uint PathCount, ModeCount;
            int error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
                out PathCount, out ModeCount);
            if (error != ERROR_SUCCESS)
            {
                throw new Win32Exception(error);
            }

            DISPLAYCONFIG_PATH_INFO[] DisplayPaths = new DISPLAYCONFIG_PATH_INFO[PathCount];
            DISPLAYCONFIG_MODE_INFO[] DisplayModes = new DISPLAYCONFIG_MODE_INFO[ModeCount];
            error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
                ref PathCount, DisplayPaths, ref ModeCount, DisplayModes, IntPtr.Zero);

            for (int i = 1; i < ModeCount; i++)
            {
                if (DisplayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
                {
                    Dictionary<string, string> item = new Dictionary<string, string>();

                    item["MonitorName"] = (MonitorFriendlyName(DisplayModes[i].adapterId, DisplayModes[i].id));
                    items.Add(item);


                }
            }

            return items;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }


    }
BongJae
  • 49
  • 5
  • 1
    You are right, the question is a bit confusing. But if I understand "without reading the second item" correctly, you can use `break;` to break out of the current loop. See if that's what you need for that part. – jegtugado Sep 07 '18 at 01:10
  • @John Ephraim Tugado I've tried using break; to get out of the inside loop but it stoped the whole loop.... – BongJae Sep 07 '18 at 01:35
  • Note that the `visual-studio` tag should _only_ be used for questions pertaining to the Visual Studio IDE, not code you have written using it (check the tag's wiki page for more information). – ProgrammingLlama Sep 07 '18 at 01:55
  • Can you show us what `DeviceSettings` is? – Parrish Husband Sep 07 '18 at 01:59
  • How do you know which `deviceName` goes with each `ManagementObject`? – Parrish Husband Sep 07 '18 at 02:09
  • So you're using `PInvoke` then, I assume from here: https://stackoverflow.com/a/28257839/1316856 – Parrish Husband Sep 07 '18 at 02:41
  • I'm not sure what your intent was in your `GetMonitorFriendlyName` method, but you've broken the functionality of the code you copied. Why are you creating a separate `Dictionary` each iteration?? – Parrish Husband Sep 07 '18 at 02:50
  • @ParrishHusband THnx! you really helped me!! – BongJae Sep 07 '18 at 05:47

3 Answers3

0

You appear to be overwriting your monitorname key in your dictionary entry every time you iterate. This would set every single item to have the same monitor name. Try something like this:

List<object> items = new List<object>();
DeviceSettings deviceSettings = new DeviceSettings();
List<object> deviceNames = deviceSettings.GetMonitorFriendlyName();

using (ManagementObjectCollection moc = searcher.Get())
{
    var managementObjects = moc.Cast<ManagementObject>().ToArray();
    ConnectedMonitor_Number = managementObjects.Length;

    for (int i = 0; i < managementObjects.Length; i++)
    {
        object device = deviceNames[i];
        ManagementObject mo = managementObjects[i];

        Dictionary<string, object> item = new Dictionary<string, object>
        {
            { "DefaultMonitorLength", DefaultMonitor_Width },
            { "DefaultMonitorHeight", DefaultMonitor_Height },
            { "ConnectedMonitor_Numb", Convert.ToString(ConnectedMonitor_Number) },
            { "Caption", Convert.ToString(mo["Caption"]) },
            { "Name", Convert.ToString(mo["Name"]) },
            { "Description", Convert.ToString(mo["Description"]) },
            { "DeviceID", Convert.ToString(mo["DeviceID"]) },
            { "Manufacturer", Convert.ToString(mo["Manufacturer"]) },
            { "HardwareID", string.Join(";", (string[])mo["HardwareID"]) },
            { "Status", Convert.ToString(mo["Status"]) },
            { "monitorname", Convert.ToString(device["monitorname"])}
        };

        items.Add(item);
    }
}

Note this doesn't compile because you are declaring deviceNames as a List<object> however appear to treat it like a Dictionary<string,string>. Is there a cast we're not seeing? Also this answer is predicated on the assumption you're searching only for connected monitors.

Update:

Seeing where you copied your source from, you need to revert your code back to what the original author was doing. If you really want a dictionary, you'll need to pick a key that you can tie into your WMI search results from above.

Parrish Husband
  • 3,148
  • 18
  • 40
0

Edit after looking at the updated code.

Your code seems to be all messed up and I am sure it is not even executing completely.

You are using same Key for dictionary (Dictionary<string, string> item) in your list of Dictionaries (List<object> items). This means, at any given time, you have exactly one value in your dictionary. What are you trying to achieve by this?

Now, coming to your question where you are trying to loop through the second foreach just once and exit.

I am seeing a major issue here. You are trying to access value of the key "monitorname" whereas, at the source, you are assigning the value to key "MonitorName".

  1. Based on your Dictionary initialisation, keys in your Dictionary are case-sensitive, and here you are trying to access wrong key.
  2. Since you always have a single entry in the dictionary with key "MonitorName", this line of code will throw KeyNotFoundException at runtime.

But you have reported that adding break; to the second foreach breaks the first foreach. My guess is that you have not even debugged the code and have posted your question on assumption based on the output you are getting. Which is caused due to runtime exception and not because the break; is not working as expected.

Although there are many things unclear in your code, I am assuming you have a valid reason to have them that way.

The below code should fix your problem:

    foreach (Dictionary<string, string> dm in deviceName)
    {
        item["monitorname"] = Convert.ToString(dm["MonitorName"]);
        break;
    }

Notice dm["MonitorName"] where I have updated the key from "monitorname" to "MonitorName".

Also remember to use correct key while accessing item["monitorname"]

Hope this helps!

dj079
  • 1,389
  • 8
  • 14
0

If I got your question this may be logic you looking for(Not sure). Use an outer loop to just hold item and an inner loop to do a real operation.

 foreach (ManagementObject mo in moc)
{
   foreach (item-no-n mo in ManagementObject )
    {
      ///1st item loop to n-item
    }
   foreach (item-no-n mo in ManagementObject )
    {
      ///1st item loop to n-item
    }

}