Getting device/driver information related to a COM port?

后端 未结 3 1337
南旧
南旧 2020-12-09 20:14

I have a Serial-to-USB device with a similarly named device driver in the Windows device manager. The devices do not always grab the same COM port on system boot, so my prog

3条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-09 21:06

    I achieved what I wanted by using the WinRegistry class provided by David in this SO question to obtain the FriendlyName from registry key associated with my USB device. I then parse out the COM number from the friendly name.

    Some things to consider:

    1. USB devices are located at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ in the registry (tested on WinXP, Win7.)

    2. I required the device VID + PID to identify the correct device key (eg. VID_xxxx&PID_xxxx.) Since VID and PID are device specific, this key should be reliable across multiple systems.

    3. The VID_xxxx&PID_xxxx key contains another sub-key with device values. I had some trouble enumerating the sub-keys with WinRegistry, so I hard-coded the sub-key name as a quick hack during development. A much safer solution would search sub-keys to find the correct name.

    4. The device keys exist in the registry regardless of whether the device is currently connected. This code makes the assumption that Windows will update FriendlyName if the device is reconnected to a different COM port. I haven't verified this, but things looked good during use-testing.

    Example

    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));
    

    Code

    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;
    }   
    

提交回复
热议问题