如何通过C#中的PID和VID发现虚拟COM端口名称 [英] How to discover the virtual COM port name knowing the PID and VID in C#

查看:57
本文介绍了如何通过C#中的PID和VID发现虚拟COM端口名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to find the correct way of finding the COM port name if I know the PID and VID. So far I wrote the workaround but i do not believe that there is no more elegant and correct way. BTW (I know that I can use REGEX). This was written only to test the workaround.

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

任何想法都值得欢迎:)

Any ideas are more than welcome :)

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; }
    }

}

它能胜任工作-但我不喜欢

It does the job - but I di not like it

推荐答案

我实际上认为您的代码看起来不错.是的,我会使用正则表达式,并且在某些可以浓缩事物的地方.但是,这些东西无助于提高性能或执行其他任何操作.仅在大多数情况下,使代码更小.我还假设此应用程序只能在Windows上运行.

I actually think your code looks good. Yes, I'd use the Regex and there are places, where things can be condensed. But, that stuff won't help improve performance or do anything else. Just, mostly, make the code smaller. I'm also assuming this app will run on Windows only.

无论如何,以下任何代码都可以提供帮助:

Anyhow, can any of this code help:

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();
        }
    }
}

这篇关于如何通过C#中的PID和VID发现虚拟COM端口名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆