Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
644 views
in Technique[技术] by (71.8m points)

c# - WMI: Get list of all serial (COM) ports including virtual ports

I'm currently working on a little C# program to interact with an Arduino microcontroller. The program has a combobox where you can choose the COM-port. The μc is connected by USB and a virtual COM-port (CH340).

I use the code below to fill in the avaible COM-ports to the combobox.

private void Form1_Load(object sender, EventArgs e)
    {
        string[] PortNames = SerialPort. GetPortNames();
        comboBoxPort.Items.AddRange(PortNames);
    }

The downside of this is, you have to take a look into the Device Manager to see which one is the correct one for the μc. My PC for example has 4 active COM-ports, one physical, 2 virtual and another virtual one for the μc. What I'm searching for is a way to display the complete Name of the device with the associated COM-port (like you can find it in the Device Manager)

COM-ports in the Device Manager

After a bit of research I found out that there is another possibility by using the WMI. After a lot of testing with the "WMI Code Creator" I don't know what else I can try to accomplish what I’ve attended to do. All the namespaces and classes I’ve tried are only generating the COM-port like COM1, COM2… or they generate the hardware-id which is not useful for the user of the program. The code below is more or less exactly what I'm searching for but it only works for “real” build in COM-ports.

using System;
using System.Management;
using System.Windows.Forms;

namespace WMISample
    {
        public class MyWMIQuery
        {
            public static void Main()
            {
                try
                {
                    ManagementObjectSearcher searcher =
                        new ManagementObjectSearcher("root\CIMV2",
                        "SELECT * FROM Win32_SerialPort");

                    foreach (ManagementObject queryObj in searcher.Get())
                    {
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Win32_SerialPort instance");
                        Console.WriteLine("-----------------------------------");
                        Console.WriteLine("Name: {0}", queryObj["Name"]);
                    }
                }
                catch (ManagementException e)
                {
                    MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
                }
            }
        }
    }

Is there any other possible way to get a list of all the COM-ports like there is one insinde of the Device Manager? Is it maybe possible to use the hardware-id of the devices to identify them somehow and then, in a second step get the correct name for them?

I would be very pleased if I could get some help with this. There must be a way to do this but I can't find it.

And sry for my english if something sounds wierd :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As mentiont before here is the complete working code to fill a combobox with all avaible COM-ports and set the associated port after seletion.

(The original answer how to get the port names --> link)

Thanks @o_O for the link and I hope someone will find this code useful.

private void Form1_Load(object sender, EventArgs e)
{
    // Get all serial (COM)-ports you can see in the devicemanager
    ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\cimv2",
        "SELECT * FROM Win32_PnPEntity WHERE ClassGuid="{4d36e978-e325-11ce-bfc1-08002be10318}"");

    // Sort the items in the combobox 
    CmdBoxPort.Sorted = true;

    // Add all available (COM)-ports to the combobox
    foreach (ManagementObject queryObj in searcher.Get())
        CmdBoxPort.Items.Add(queryObj["Caption"]);
}

private void CmdBoxPort_SelectedIndexChanged(object sender, EventArgs e)
{
    // Set the right port for the selected item.
    // The portname is based on the "COMx" part of the string (SelectedItem)
    string item = CmdBoxPort.SelectedItem.ToString();

    // Search for the expression "(COM" in the "selectedItem" string
    if (item.Contains("(COM"))
    {
        // Get the index number where "(COM" starts in the string
        int indexOfCom = item.IndexOf("(COM");

        // Set PortName to COMx based on the expression in the "selectedItem" string
        // It automatically gets the correct length of the COMx expression to make sure 
        // that also a COM10, COM11 and so on is working properly.
        serialPort1.PortName = item.Substring(indexOfCom + 1, item.Length - indexOfCom - 2);
    }
    else
        return;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...