java - 获取与 COM 端口相关的设备/驱动程序信息?

标签 java windows serial-port device-driver

我有一个串口转 USB 设备,在 Windows 设备管理器中有一个类似名称的设备驱动程序。这些设备并不总是在系统启动时占用相同的 COM 端口,因此我的程序需要在启动时识别它。

我试过使用 RXTX枚举系统上的 COM 端口,但这没有用,因为 CommPortIdentifier.getName() 只是返回 COM 名称(例如 COM1、COM2 等)我需要获取驱动程序制造商名称或出现在设备管理器中的驱动程序名称,并将其与 COM 名称相关联。

这可以用 Java 轻松完成吗? (我会对支持此功能的任何第 3 方 Java 库感兴趣。)否则,我如何通过 win32 API 开始完成此操作?

最佳答案

我通过使用 David 在 this SO question 中提供的 WinRegistry 类实现了我想要的。从与我的 USB 设备关联的注册表项中获取 FriendlyName。然后我从友好名称中解析出 COM 编号。

一些需要考虑的事情:

  1. USB 设备位于注册表中的 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\(已在 WinXP、Win7 上测试。)

  2. 我需要设备 VID + PID 来识别正确的设备 key (例如 VID_xxxx&PID_xxxx。)由于 VID 和 PID 是特定于设备的,因此该 key 在多个系统中应该是可靠的。

  3. VID_xxxx&PID_xxxx 键包含另一个具有设备值的子键。我在使用 WinRegistry 枚举子键时遇到了一些麻烦,因此我在开发过程中将子键名称硬编码为快速破解。一种更安全的解决方案是搜索子键以找到正确的名称。

  4. 无论设备当前是否已连接,设备 key 都存在于注册表中。此代码假设如果设备重新连接到不同的 COM 端口,Windows 将更新 FriendlyName。我尚未对此进行验证,但在使用测试期间看起来一切正常。

例子

String keyPath = "SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\";
String device1 = "5&75451e6&0&1";
System.out.println("First COM device: " + getComNumber(keyPath + device1));

代码

import java.util.regex.Pattern;
import java.util.regex.Matcher;

// Given a registry key, attempts to get the 'FriendlyName' value
// Returns null on failure.
//
public static String getFriendlyName(String registryKey) {
    if (registryKey == null || registryKey.isEmpty()) {
        throw new IllegalArgumentException("'registryKey' null or empty");
    }
    try {
        int hkey = WinRegistry.HKEY_LOCAL_MACHINE;
        return WinRegistry.readString(hkey, registryKey, "FriendlyName");
    } catch (Exception ex) { // catch-all: 
        // readString() throws IllegalArg, IllegalAccess, InvocationTarget
        System.err.println(ex.getMessage());
        return null;
    }
}

// Given a registry key, attempts to parse out the integer after
// substring "COM" in the 'FriendlyName' value; returns -1 on failure.
//
public static int getComNumber(String registryKey) {
    String friendlyName = getFriendlyName(registryKey);

    if (friendlyName != null && friendlyName.indexOf("COM") >= 0) {
        String substr = friendlyName.substring(friendlyName.indexOf("COM"));
        Matcher matchInt = Pattern.compile("\\d+").matcher(substr);
        if (matchInt.find()) {
            return Integer.parseInt(matchInt.group());
        }
    }
    return -1;
}   

关于java - 获取与 COM 端口相关的设备/驱动程序信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6362775/

相关文章:

java - Doc 和 Docx 到 PDF 的转换,在 Linux 上使用 Java

java - 如果我的批处理文件路径中有空格,为什么会出现错误?

linux - 如何确保仅当脚本在 Windows 上运行时才加载模块?

linux - linux上的软件串口环回

objective-c - Mac 相当于 .Net SerialPort.ReadExisting()

c++ - 将类添加到基本 Qt GUI 应用程序时出现 Qt 链接器错误

java - 如何编写正则匹配表达式。 -Java

java - 无法更新图像 "JLabel setIcon"

java - 如何反序列化Java中隐藏的ServiceProvider类对象?

windows - 批量标准化文件路径