Define COM port using VID and PID for x64 USB device

How can I get usb com port names attached to a 32-bit win7OS machine using pid and vid, but when working on x64 it got stuck in the following line:

comports.Add((string)rk6.GetValue("PortName")); 

This is my code.

 static List<string> ComPortNames(String VID, String PID) { String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID); Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase); List<string> comports = new List<string>(); RegistryKey rk1 = Registry.LocalMachine; RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum"); 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"); comports.Add((string)rk6.GetValue("PortName")); } } } } return comports; } 

the actual get code is here . So, how to get the COM port names in x64, any suggestion?

+6
source share
5 answers

After reading the code, I found out that the current path you are viewing in the registry does not contain any port information. But I found a way to read it by making this small change:

  static List<string> ComPortNames(String VID, String PID) { String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID); Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase); List<string> comports = new List<string>(); RegistryKey rk1 = Registry.LocalMachine; RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum"); 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); string location = (string)rk5.GetValue("LocationInformation"); if (!String.IsNullOrEmpty(location)) { string port = location.Substring(location.IndexOf('#') + 1, 4).TrimStart('0'); if (!String.IsNullOrEmpty(port)) comports.Add(String.Format("COM{0:####}", port)); } //RegistryKey rk6 = rk5.OpenSubKey("Device Parameters"); //comports.Add((string)rk6.GetValue("PortName")); } } } } return comports; } 

This worked perfectly. Thanks for your code, by the way ... It helped me a lot!

+6
source

I think ManagementObjectSearcher might be a better approach than reading the registry directly.

Here is an example for virtual COM ports.

+2
source

While I tested Youkko's answer on Windows 10 x64, I got some strange results and looked at the registry of my machine LocationInformation keys contained lines, such as Port_#0002.Hub_#0003 , so they are connected to the USB hub / port to which the device is connected , and not to the COM port allocated by Windows.

So, in my case, I turned on COM2, which is the hardware port on my motherboard, and it skipped the COM5 port, which I expected, but it was located in the PortName registry PortName . I'm not sure if something has changed from the version of Windows you used, but I think that your main problem may not have been checking the null values ​​on the keys.

The following slightly modified version works fine on systems with multiple or Windows 7/10 and x32 / 64, and I also added a SerialPort.GetPortNames() check to make sure the device is accessible and connected to the system before returning:

 static List<string> ComPortNames(String VID, String PID) { String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID); Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase); List<string> comports = new List<string>(); RegistryKey rk1 = Registry.LocalMachine; RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum"); 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); string location = (string)rk5.GetValue("LocationInformation"); RegistryKey rk6 = rk5.OpenSubKey("Device Parameters"); string portName = (string)rk6.GetValue("PortName"); if (!String.IsNullOrEmpty(portName) && SerialPort.GetPortNames().Contains(portName)) comports.Add((string)rk6.GetValue("PortName")); } } } } return comports; } 
+2
source

Here is my approach to this (even if it is not direct A for Q)

  • USB devices are always (and always) listed under HKLM\SYSTEM\CurrentControlSet\Enum\USB (note USB at the end)
    • Device nodes are in the format VID_xxxx&PID_xxxx* , where xxxx is hexadecimal, at the end there may be some additional function data
    • Each node device has an auxiliary node identifier based on the serial number or other device data and functions
    • the node identifier can be set to "FriendlyName" , which sometimes has COM in brackets such as "Virtual Serial Port (COM6)"
    • The resulting path: HKLM\SYSTEM\CurrentControlSet\Enum\USB\VID_xxxx&PID_xxxx*\*\Device Parameters\ has a value with the name "PortName"
  • Available COM ports are listed by System.IO.Ports.SerialPort.GetPortNames()
  • OpenSubKey implements IDisposable and must have using or .Dispose() on them

     using System.IO.Ports; using System.Linq; using Microsoft.Win32; public class UsbSerialPort { public readonly string PortName; public readonly string DeviceId; public readonly string FriendlyName; private UsbSerialPort(string name, string id, string friendly) { PortName = name; DeviceId = id; FriendlyName = friendly; } private static IEnumerable<RegistryKey> GetSubKeys(RegistryKey key) { foreach (string keyName in key.GetSubKeyNames()) using (var subKey = key.OpenSubKey(keyName)) yield return subKey; } private static string GetName(RegistryKey key) { string name = key.Name; int idx; return (idx = name.LastIndexOf('\\')) == -1 ? name : name.Substring(idx + 1); } public static IEnumerable<UsbSerialPort> GetPorts() { var existingPorts = SerialPort.GetPortNames(); using (var enumUsbKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Enum\USB")) { if (enumUsbKey == null) throw new ArgumentNullException("USB", "No enumerable USB devices found in registry"); foreach (var devBaseKey in GetSubKeys(enumUsbKey)) { foreach (var devFnKey in GetSubKeys(devBaseKey)) { string friendlyName = (string) devFnKey.GetValue("FriendlyName") ?? (string) devFnKey.GetValue("DeviceDesc"); using (var devParamsKey = devFnKey.OpenSubKey("Device Parameters")) { string portName = (string) devParamsKey?.GetValue("PortName"); if (!string.IsNullOrEmpty(portName) && existingPorts.Contains(portName)) yield return new UsbSerialPort(portName, GetName(devBaseKey) + @"\" + GetName(devFnKey), friendlyName); } } } } } public override string ToString() { return string.Format("{0} Friendly: {1} DeviceId: {2}", PortName, FriendlyName, DeviceId); } } 
+1
source

Ok, using ManagementObjectSearcher (it gives the COM port index and VID and PID if they exist):

  List < List <string>> USBCOMlist = new List<List<string>>(); try { ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity"); foreach (ManagementObject queryObj in searcher.Get()) { if (queryObj["Caption"].ToString().Contains("(COM")) { List<string> DevInfo = new List<string>(); string Caption = queryObj["Caption"].ToString(); int CaptionIndex = Caption.IndexOf("(COM"); string CaptionInfo = Caption.Substring(CaptionIndex + 1).TrimEnd(')'); // make the trimming more correct DevInfo.Add(CaptionInfo); string deviceId = queryObj["deviceid"].ToString(); //"DeviceID" int vidIndex = deviceId.IndexOf("VID_"); int pidIndex = deviceId.IndexOf("PID_"); string vid = "", pid = ""; if (vidIndex != -1 && pidIndex != -1) { string startingAtVid = deviceId.Substring(vidIndex + 4); // + 4 to remove "VID_" vid = startingAtVid.Substring(0, 4); // vid is four characters long //Console.WriteLine("VID: " + vid); string startingAtPid = deviceId.Substring(pidIndex + 4); // + 4 to remove "PID_" pid = startingAtPid.Substring(0, 4); // pid is four characters long } DevInfo.Add(vid); DevInfo.Add(pid); USBCOMlist.Add(DevInfo); } } } catch (ManagementException e) { MessageBox.Show(e.Message); } 
0
source

Source: https://habr.com/ru/post/914329/


All Articles