使用VID和PID为连接到x64的USB设备识别COM端口

Uda*_*mal 6 c# usb 64-bit usbserial

如下我能够通过给定的pid和vid获得附加到32位win7OS机器的usb com端口名称,但是当在x64中运行时它会卡在以下行中:

comports.Add((string)rk6.GetValue("PortName"));
Run Code Online (Sandbox Code Playgroud)

这是我的代码

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;
    }
Run Code Online (Sandbox Code Playgroud)

实际代码到了这里,那么如何在x64中获取com端口名称,有什么建议吗?

You*_*kko 6

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

    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;
    }
Run Code Online (Sandbox Code Playgroud)

它做得很好.谢谢你的代码,顺便说一句......它给了我很多帮助!

  • 另外,使用“if (!String.IsNullOrEmpty(location))”而不是“if (location != string.Empty)”...我发现位置可以为空。 (2认同)

Pet*_*erJ 6

当我在Windows 10 x64下测试来自Youkko的答案时,我得到了一些奇怪的结果,并查看了我计算机上的注册表,这些LocationInformation键包含字符串,例如,Port_#0002.Hub_#0003它们与设备连接到USB端口的USB集线器/端口有关,而不是与COM相连。 Windows分配的端口。

因此,以我为例,我获得了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;
}
Run Code Online (Sandbox Code Playgroud)