C# 使用连接到x64的USB设备的VID和PID标识COM端口

C# 使用连接到x64的USB设备的VID和PID标识COM端口,c#,usb,64-bit,usbserial,C#,Usb,64 Bit,Usbserial,如下所示,通过给定的pid和vid,我能够获得连接到32位win7OS机器的usb com端口名,但在x64中运行时,它卡在以下行中: comports.Add((string)rk6.GetValue("PortName")); 这是我的密码 static List<string> ComPortNames(String VID, String PID) { String pattern = String.Format("^VID_{0}.PID_{1}"

如下所示,通过给定的pid和vid,我能够获得连接到32位win7OS机器的usb com端口名,但在x64中运行时,它卡在以下行中:

comports.Add((string)rk6.GetValue("PortName"));
这是我的密码

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;
    }
静态列表组件名(字符串VID、字符串PID)
{
字符串模式=String.Format(“^VID{0}.PID{1}”,VID,PID);
正则表达式_rx=新正则表达式(模式,RegexOptions.IgnoreCase);
List comports=新列表();
RegistryKey rk1=Registry.LocalMachine;
注册表项rk2=rk1.OpenSubKey(“系统\\CurrentControlSet\\Enum”);
foreach(rk2.GetSubKeyNames()中的字符串s3)
{
注册表项rk3=rk2.OpenSubKey(s3);
foreach(rk3.GetSubKeyNames()中的字符串s)
{
如果(接收匹配成功)
{
注册表项rk4=rk3.OpenSubKey;
foreach(rk4.GetSubKeyNames()中的字符串s2)
{
注册表项rk5=rk4.OpenSubKey(s2);
注册表项rk6=rk5.OpenSubKey(“设备参数”);
Add((字符串)rk6.GetValue(“端口名”);
}
}
}
}
返回组件;
}
实际代码获取,那么如何在x64中获取com端口名,有什么建议吗?

我认为这可能是比直接读取注册表更好的方法


以下是虚拟COM端口。

通过阅读您的代码,我发现您在注册表中查看的当前路径不包含任何有关端口的信息。 但我找到了一种阅读它的方法,做了一点小小的改变:

    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;
    }
静态列表组件名(字符串VID、字符串PID)
{
字符串模式=String.Format(“^VID{0}.PID{1}”,VID,PID);
正则表达式_rx=新正则表达式(模式,RegexOptions.IgnoreCase);
List comports=新列表();
RegistryKey rk1=Registry.LocalMachine;
注册表项rk2=rk1.OpenSubKey(“系统\\CurrentControlSet\\Enum”);
foreach(rk2.GetSubKeyNames()中的字符串s3)
{
注册表项rk3=rk2.OpenSubKey(s3);
foreach(rk3.GetSubKeyNames()中的字符串s)
{
如果(接收匹配成功)
{
注册表项rk4=rk3.OpenSubKey;
foreach(rk4.GetSubKeyNames()中的字符串s2)
{
注册表项rk5=rk4.OpenSubKey(s2);
字符串位置=(字符串)rk5.GetValue(“位置信息”);
如果(!String.IsNullOrEmpty(位置))
{
字符串端口=location.Substring(location.IndexOf('#')+1,4).TrimStart('0');
if(!String.IsNullOrEmpty(port))comports.Add(String.Format(“COM{0:######}”,port));
}
//注册表项rk6=rk5.OpenSubKey(“设备参数”);
//Add((字符串)rk6.GetValue(“端口名”);
}
}
}
}
返回组件;
}
它确实工作得很好。
谢谢你的代码,顺便说一下。。。这对我帮助很大

当我在Windows 10 x64下测试答案时,我得到了一些奇怪的结果,并查看了我机器上的注册表,
位置信息
键包含字符串,如
端口0002.Hub#0003
,因此它们与设备连接的USB集线器/端口相关,而不是与设备分配的COM端口相关窗户

因此,在我的例子中,我得到了COM2,它是我主板上的一个硬件端口,它跳过了我期望的COM5端口,但它位于
PortName
注册表项下。我不确定自您使用的Windows版本以来是否发生了变化,但我认为您的主要问题可能是没有检查键上的空值

以下稍作修改的版本似乎可以在各种Windows 7/10和x32/64系统上正常工作,我还添加了一个用于检查
SerialPort.GetPortNames()
,以确保设备可用并在返回之前插入系统:

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;
}
静态列表组件名(字符串VID、字符串PID)
{
字符串模式=String.Format(“^VID{0}.PID{1}”,VID,PID);
正则表达式_rx=新正则表达式(模式,RegexOptions.IgnoreCase);
List comports=新列表();
RegistryKey rk1=Registry.LocalMachine;
注册表项rk2=rk1.OpenSubKey(“系统\\CurrentControlSet\\Enum”);
foreach(rk2.GetSubKeyNames()中的字符串s3)
{
注册表项rk3=rk2.OpenSubKey(s3);
foreach(rk3.GetSubKeyNames()中的字符串s)
{
如果(接收匹配成功)
{
注册表项rk4=rk3.OpenSubKey;
foreach(rk4.GetSubKeyNames()中的字符串s2)
{
注册表项rk5=rk4.OpenSubKey(s2);
字符串位置=(字符串)rk5.GetValue(“位置信息”);
注册表项rk6=rk5.OpenSubKey(“设备参数”);
字符串portName=(字符串)rk6.GetValue(“portName”);
如果(!String.IsNullOrEmpty(portName)&&SerialPort.GetPortNames().Contains(portName))
Add((字符串)rk6.GetValue(“端口名”);
}
}
}
}
返回组件;
}
以下是我对这一点的看法(即使这不是直接的a到Q)

  • USB设备总是(并且一直)在
    HKLM\SYSTEM\CurrentControlSet\Enum\USB
    下枚举(注意
    USB
    • 设备节点的格式为
      VID_xxxx&PID_xxxx*
      ,其中
      xxxx
      为十六进制,可能在末尾有一些额外的函数数据
    • 每个设备节点都有一个基于序列号或其他数据的子标识符节点
      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);
          }
      }
      
              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);
              }