Giới thiệu

List com port with csharp

Trong 1 Project có giao tiếp với mạch điều khiển bên ngoài qua giao diện GUI trên máy tính, phần ứng dụng viết bằng C# có nhiệm vụ tạo kết nối giữa ứng dụng trên máy tính với mạch giao tiếp bên ngoài thông qua cổng COM đã được chọn. Để ứng dụng liên tục cập nhật các cổng COM hiện có thì chúng ta sử dụng Timer để định thời cho ứng dụng quét cổng COM sau mỗi 1 thời gian interval định trước.

1. Cách nhanh, đơn giản

Thường thì khi ta list ra danh sách các cổng COM hiện có trên máy tính, chúng ta sử dụng phương thức:

string[] ports = SerialPort.GetPortNames();

Kết quả thì hệ thống sẽ trả về danh sách các cổng dạng COM1, COM2… hiện tại đang có trên hệ thống vào mảng ports[].

Giả sử danh sách cập nhật cổng COM được đưa vào ComboBox có tên cbb_COMPort.

Mã nguồn đoạn quét cổng COM với cách thức này như sau:

private void timer1_Tick(object sender, EventArgs e)
{
    //Timer to update
    string[] ports = SerialPort.GetPortNames(); //Get list COM ports
    if (intlen != ports.Length)
    {
        intlen = ports.Length;
        cbb_COMPort.Items.Clear();
        for(int i = 0; i < intlen; i++)
        {
            cbb_COMPort.Items.Add(ports[i]);
        }
    }
}

Kết quả:

List COM port

Vì đơn giản như vậy, để xác định chính xác là thiết bị nào ứng với cổng COM nào thì chúng ta phải xem lại trong Device Manager -> Port (COM & LPT) để kết nối được chính xác.

2. Cách phức tạp hơn 1 chút

Cách dưới đây sẽ cho phép chúng ta hiển thị ngay tên định danh của từng thiết bị tương ứng với cổng COM mà thiết bị đó kết nối vào.

Yêu cầu: Add thêm Reference System.Management cho Project của bạn: Project -> Add Reference -> System.Management; Thêm dòng using System.Management; vào phần đầu của chương trình (Header). Sau đó là thêm đoạn mã dưới đây vào cuối chương trình của bạn.

internal class ProcessConnection
{
    public static ConnectionOptions ProcessConnectionOptions()
    {
        ConnectionOptions options = new ConnectionOptions();
        options.Impersonation = ImpersonationLevel.Impersonate;
        options.Authentication = AuthenticationLevel.Default;
        options.EnablePrivileges = true;
        return options;
    }

    public static ManagementScope ConnectionScope(string machineName, ConnectionOptions options, string path)
    {
        ManagementScope connectScope = new ManagementScope();
        connectScope.Path = new ManagementPath(@"\\" + machineName + path);
        connectScope.Options = options;
        connectScope.Connect();
        return connectScope;
    }
}

public class COMPortInfo
{
    public string Name { get; set; }
    public string Description { get; set; }

    public COMPortInfo() { }

    public static List<COMPortInfo> GetCOMPortsInfo()
    {
        List<COMPortInfo> comPortInfoList = new List<COMPortInfo>();

        ConnectionOptions options = ProcessConnection.ProcessConnectionOptions();
        ManagementScope connectionScope = ProcessConnection.ConnectionScope(Environment.MachineName, options, @"\root\CIMV2");

        ObjectQuery objectQuery = new ObjectQuery("SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0");
        ManagementObjectSearcher comPortSearcher = new ManagementObjectSearcher(connectionScope, objectQuery);

        using (comPortSearcher)
        {
            string caption = null;
            foreach (ManagementObject obj in comPortSearcher.Get())
            {
                if (obj != null)
                {
                    object captionObj = obj["Caption"];
                    if (captionObj != null)
                    {
                        caption = captionObj.ToString();
                        if (caption.Contains("(COM"))
                        {
                            COMPortInfo comPortInfo = new COMPortInfo();
                            comPortInfo.Name = caption.Substring(caption.LastIndexOf("(COM")).Replace("(", string.Empty).Replace(")", string.Empty);
                            comPortInfo.Description = caption;
                            comPortInfoList.Add(comPortInfo);
                        }
                    }
                }
            }
        }
        return comPortInfoList;
    }
}

Đoạn mã trên sẽ truy cập vào hệ thống và lấy ra những thuộc tính của các cổng COM, trong đó quan trọng là tên cổng COM (Name) và tên định danh - mô tả (Description).

Sử dụng:

private void timer1_Tick(object sender, EventArgs e)
{
    string[] ports = SerialPort.GetPortNames();
    if (intlen != ports.Length) //Change?
    {
        intlen = ports.Length;
        cbb_COMPort.Items.Clear();
        foreach (COMPortInfo PortCOMs in COMPortInfo.GetCOMPortsInfo())
        {
            cbb_COMPort.Items.Add(string.Format("{0} – {1}", PortCOMs.Name, PortCOMs.Description));
        }
        cbb_COMPort.SelectedIndex = 0;
    }
}

Đoạn mã trên sẽ hiển thị ra danh sách các tùy chọn cổng COM ví dụ như: “COM3 - Texas Instrument LaunchPad”.

Kết quả:

COM với tên định danh

Enjoy!