【问题标题】:How to discover the virtual COM port name knowing the PID and VID in C#如何在 C# 中发现知道 PID 和 VID 的虚拟 COM 端口名称
【发布时间】:2018-05-26 14:43:28
【问题描述】:

如果我知道 PID 和 VID,我正在尝试找到查找 COM 端口名称的正确方法。到目前为止,我写了解决方法,但我不相信没有更优雅和正确的方法。顺便说一句(我知道我可以使用 REGEX)。这只是为了测试解决方法而编写的。

我知道有很大的改进空间,我不要求进行代码审查

任何想法都非常受欢迎:)

namespace ConsoleApplication1
{
    using System;
    using System.Globalization;
    using System.Collections.Generic;
    using System.Management; 
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            VCOMDetect VCOMPorts = new VCOMDetect(0x0483, 0xA27D);


            Console.WriteLine("BootPort: {0}", VCOMPorts.BootPort() ?? "Not detected");
            Console.WriteLine("Oscilloscope Port: {0}", VCOMPorts.OscilloscopePort() ?? "Not detected");
            Console.WriteLine("Serial/USB Port: {0}", VCOMPorts.SerialPort() ?? "Not detected");
            Console.WriteLine("Programming Port: {0}", VCOMPorts.ProgPort() ?? "Not detected");

            Console.Read();
        }

    }


    class VCOMDetect
    {

        private const string USB_BOOTLOADER_SERIAL   = "000000000b00";
        private const string USB_OSCILLOSCOPE_SERIAL = "000000000c00";
        private const string USB_VCOM_SERIAL         = "000000000d00";
        private const string USB_PRG_SERIAL          = "000000000e00";

        private List<VCOM_USBDeviceInfo> PortsList;

        public VCOMDetect(UInt16 vid, UInt16 pid)
        {
            PortsList = GetUSBDevices(vid, pid);
        }

        public string BootPort()
        {
            foreach(VCOM_USBDeviceInfo VCOM in PortsList)
            {
                if (VCOM.Serial.ToLower() == USB_BOOTLOADER_SERIAL.ToLower()) return VCOM.COMPort;
            }
            return null;
        }

        public string OscilloscopePort()
        {
            foreach (VCOM_USBDeviceInfo VCOM in PortsList)
            {
                if (VCOM.Serial.ToLower() == USB_OSCILLOSCOPE_SERIAL.ToLower()) return VCOM.COMPort;
            }
            return null;
        }

        public string SerialPort()
        {
            foreach (VCOM_USBDeviceInfo VCOM in PortsList)
            {
                if (VCOM.Serial.ToLower() == USB_VCOM_SERIAL.ToLower()) return VCOM.COMPort;
            }
            return null;
        }

        public string ProgPort()
        {
            foreach (VCOM_USBDeviceInfo VCOM in PortsList)
            {
                if (VCOM.Serial.ToLower() == USB_PRG_SERIAL.ToLower()) return VCOM.COMPort;
            }
            return null;
        }


        private List<VCOM_USBDeviceInfo> GetUSBDevices(UInt16 vid, UInt16 pid)
        {
            List<VCOM_USBDeviceInfo> VCOM_devices = new List<VCOM_USBDeviceInfo>();

            ManagementObjectCollection collection;
            using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity"))
                collection = searcher.Get();

            foreach (var device in collection)
            {
                var USBInfo = new VCOM_USBDeviceInfo((string)device.GetPropertyValue("DeviceID"));

                if (USBInfo.PID == 0 || USBInfo.VID == 0) continue;
                if (USBInfo.PID != pid || USBInfo.VID != vid) continue;

                USBInfo.Caption = (string)device.GetPropertyValue("Caption");
                if (USBInfo.COMPort == "") continue;

                USBInfo.PnpDeviceID = (string)device.GetPropertyValue("PNPDeviceID");
                USBInfo.Description = (string)device.GetPropertyValue("Description");
                VCOM_devices.Add(USBInfo);
            }

            collection.Dispose();
            return VCOM_devices;
        }
    }

    class VCOM_USBDeviceInfo
    {
        private UInt16 _PID, _VID;
        private string _Caption;
        private void _ResetData()
        {
            this.PID = 0;
            this.VID = 0;
            this.COMnumber = -1;
            this.COMPort = "";
            this.Serial = "";
        }

        public VCOM_USBDeviceInfo(string DeviceID)
        {
            int VIDIndex = DeviceID.IndexOf("VID_");
            int PIDIndex = DeviceID.IndexOf("PID_");
            int VIDIndexEnd = -1;
            int PIDIndexEnd = -1;

            string PIDSubstring, VIDSubstring;

            if (PIDIndex == -1 || VIDIndex == -1)
            {
                _ResetData();
            }
            else
            {
                bool result = true;

                PIDSubstring = DeviceID.Substring(PIDIndex + 4);
                VIDSubstring = DeviceID.Substring(VIDIndex + 4);

                PIDIndexEnd = PIDSubstring.IndexOf("\\");
                VIDIndexEnd = VIDSubstring.IndexOf("&");

                if(PIDIndexEnd == -1 || VIDIndexEnd == -1)
                {
                    _ResetData();
                }
                else
                {

                    result = result && UInt16.TryParse(PIDSubstring.Substring(0, PIDIndexEnd), NumberStyles.AllowHexSpecifier, null, out _PID) && UInt16.TryParse(VIDSubstring.Substring(0, VIDIndexEnd), NumberStyles.AllowHexSpecifier, null, out _VID);
                    if(!result)
                    {
                        _ResetData();
                    }
                    else
                    {
                        PID = _PID;
                        VID = _VID;
                        Serial = PIDSubstring.Substring(PIDIndexEnd + 1);
                    }
                }

            }

        }

        public string DeviceID { get; set; }
        public string PnpDeviceID { get; set; }
        public string Description { get; set; }
        public string Caption
        {
            get
            {
                return _Caption;
            }
            set
            {
                int COMindex = value.IndexOf("(COM");
                string tmpCOMPort = COMindex == -1 ? "" : value.Substring(COMindex + 1, 4);
                if(COMPort == null || COMPort.Length == 0)
                {
                    COMPort = tmpCOMPort;
                }
                else
                {
                    if(COMPort != tmpCOMPort)
                    {
                        Console.WriteLine("Inconsistent COM port information");
                    }
                }
                _Caption = value;

            }
        }

        public UInt16 PID { get; set; }
        public UInt16 VID { get; set; }
        public string Serial { get; set; }
        public int COMnumber { get; set; }
        public string COMPort { get; set; }
    }

}

它可以完成工作 - 但我不喜欢它

【问题讨论】:

    标签: c# .net usb virtual-serial-port


    【解决方案1】:

    我实际上认为您的代码看起来不错。是的,我会使用正则表达式,并且有些地方可以压缩内容。但是,这些东西无助于提高性能或做任何其他事情。只是,主要是使代码更小。我还假设这个应用程序只能在 Windows 上运行。

    无论如何,这些代码中的任何一个都可以提供帮助吗:

    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.IO.Ports;
    using System.Text.RegularExpressions;
    
    namespace PortNames
    {
        class Program
        {
            static List<string> ComPortNames(String VID, String PID)
            {
                RegistryKey rk1 = Registry.LocalMachine;
                RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
    
                String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);
                Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
                List<string> ports = new List<string>();
    
                foreach (String s3 in rk2.GetSubKeyNames())
                {
                    RegistryKey rk3 = rk2.OpenSubKey(s3);
                    foreach (String s in rk3.GetSubKeyNames())
                    {
                        if (_rx.Match(s).Success)
                        {
                            RegistryKey rk4 = rk3.OpenSubKey(s);
                            foreach (String s2 in rk4.GetSubKeyNames())
                            {
                                RegistryKey rk5 = rk4.OpenSubKey(s2);
                                RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                                ports.Add((string)rk6.GetValue("PortName"));
                            }
                        }
                    }
                }
                return ports;
            }
    
            static void Main(string[] args)
            {
                List<string> names = ComPortNames("0403", "6001");
                if (names.Count > 0) foreach (String s in SerialPort.GetPortNames()) { Console.WriteLine(s); }
    
                Console.ReadLine();
            }
        }
    }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Management;
    using System.Text.RegularExpressions;
    
    namespace PortNames
    {
        class Program
        {
            private const string vidPattern = @"VID_([0-9A-F]{4})";
            private const string pidPattern = @"PID_([0-9A-F]{4})";
    
            struct ComPort // custom struct with our desired values
            {
                public string name;
                public string vid;
                public string pid;
                public string description;
            }
    
            private static List<ComPort> GetSerialPorts()
            {
                using (var searcher = new ManagementObjectSearcher
                    ("SELECT * FROM WIN32_SerialPort"))
                {
                    var ports = searcher.Get().Cast<ManagementBaseObject>().ToList();
                    return ports.Select(p =>
                    {
                        ComPort c = new ComPort();
                        c.name = p.GetPropertyValue("DeviceID").ToString();
                        c.vid = p.GetPropertyValue("PNPDeviceID").ToString();
                        c.description = p.GetPropertyValue("Caption").ToString();
    
                        Match mVID = Regex.Match(c.vid, vidPattern, RegexOptions.IgnoreCase);
                        Match mPID = Regex.Match(c.vid, pidPattern, RegexOptions.IgnoreCase);
    
                        if (mVID.Success)
                            c.vid = mVID.Groups[1].Value;
                        if (mPID.Success)
                            c.pid = mPID.Groups[1].Value;
    
                        return c;
    
                    }).ToList();
                }
            }
            static void Main(string[] args)
            {
                List<ComPort> ports = GetSerialPorts();
                //if we want to find one device
                ComPort com = ports.FindLast(c => c.vid.Equals("0483") && c.pid.Equals("5740"));
                //or if we want to extract all devices with specified values:
                List<ComPort> coms = ports.FindAll(c => c.vid.Equals("0483") && c.pid.Equals("5740"));
    
                Console.ReadLine();
            }
        }
    }
    

    【讨论】:

    • 你认为这能满足你的需要吗?
    • 其实我需要发现连接的。
    • 这不是吗?应该为您提供连接到给定端口的设备。好吧,我再弄点东西。
    • 更新了之前的答案。问题是,我没有你做的测试设备。
    猜你喜欢
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    相关资源
    最近更新 更多