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

| 我在Windows设备管理器中有一个带有USB设备的串行设备,其名称类似。设备在系统启动时并不总是抓住相同的COM端口,因此我的程序需要在启动时识别它。 我曾尝试使用RXTX枚举系统上的COM端口,但这没有用,因为
CommPortIdentifier.getName()
只是返回COM名称(例如COM1,COM2等),我需要获取驱动程序制造商名称,或设备管理器中显示的驱动程序名称,并将其与COM名称相关联。 可以用Java轻松完成吗? (我会对支持此功能的任何第三方Java库都感兴趣。)否则,我如何才能通过win32 API来实现这一目标?     
已邀请:
        通过在此SO问题中使用David提供的
WinRegistry
类,从与我的USB设备关联的注册表项中获取FriendlyName,我达到了我想要的。然后,我从友好名称中解析出COM号。 要考虑的一些事情: USB设备位于注册表中的“ 2”处(在WinXP,Win7上进行了测试。) 我需要设备VID + PID来标识正确的设备密钥(例如
VID_xxxx&PID_xxxx
)。由于VID和PID是特定于设备的,因此该密钥在多个系统之间应该是可靠的。 “ 3”键包含另一个带有设备值的子键。我在用ѭ1枚举子密钥时遇到了一些麻烦,因此在开发过程中我将子密钥名称硬编码为快速技巧。一种更安全的解决方案是搜索子项以找到正确的名称。 不管设备当前是否连接,设备密钥都存在于注册表中。此代码假定如果设备重新连接到其他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;
}   
    
        @robjb您的代码不允许连接多个设备。用户将如何知道设备名称?我添加到您的代码中,从而返回了com端口列表:
    ArrayList<String> subKeys = WinRegistry.readStringSubKeys(WinRegistry.HKEY_LOCAL_MACHINE, keyPath);
    ArrayList<Integer> comPorts = new ArrayList<Integer>();
    for (String subKey : subKeys) {
        String friendlyName = getFriendlyName(keyPath + subKey);
        if (friendlyName != null && friendlyName.contains(\"MyDriverName\") && friendlyName.contains(\"COM\")) {
            int beginIndex = friendlyName.indexOf(\"COM\") + 3 /*length of \'COM\'*/;
            int endIndex = friendlyName.indexOf(\")\");
            comPorts.add(Integer.parseInt(friendlyName.substring(beginIndex, endIndex)));
        }
    }
更新:我不认为这些是解决方案。为什么?此信息静态存储在注册表中-即使未连接设备也是如此。     
        一个很好的例子,在这里使用JNA。 作者(Geir Arne Ruud)已根据公共领域许可发布了它。 我的示例代码
public static String getFriendlyName(GoGPSModel model, String name) 
{
   if(model.getSystem().getOSType() != OSType.Windows32 
   && model.getSystem().getOSType() != OSType.Windows64) {
      return name;
   }
   for (DeviceInformation devInfo : infoObjects) {
      System.out.println(devInfo.toString());
      String friendlyName = devInfo.getFriendlyName();
      if(friendlyName != null && !friendlyName.equals(\"\") && friendlyName.contains(name)) {
         return devInfo.getManufacturer() + \": \" + friendlyName;
      }
   }
   return name;
}
    

要回复问题请先登录注册