Getting device/driver information related to a COM port?

12,674

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;
}   
Share:
12,674
Rob
Author by

Rob

B.S. Computer Science, Western Michigan University.

Updated on July 10, 2022

Comments

  • Rob
    Rob almost 2 years

    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 program needs to identify it on start up.

    I've tried using RXTX to enumerate the COM ports on the system, but this didn't work because CommPortIdentifier.getName() simply returns the COM name (eg. COM1, COM2, etc.) I need to acquire either the driver manufacturer name, or the driver name as it appears in the device manager, and associate it with the COM name.

    Can this easily be done in Java? (I'd be interested in any 3rd party Java libraries that support this.) Otherwise, how I could begin to accomplish this via the win32 API?

  • likejudo
    likejudo about 11 years
    Is there no way to simply get the driver name for the device connected to that com port?
  • Rob
    Rob about 11 years
    @Anil Check out the getFriendlyName() method I've refactored out from getComNumber(). Unfortunately the friendly name isn't always that friendly.
  • Ben Voigt
    Ben Voigt about 11 years
    Assuming that a COM port is only a single digit... broken!
  • likejudo
    likejudo about 11 years
    @robjb Looking in my xp registry, I see that the usb device is listed in ControlSet003 and CurrentControlSet. Any reason to prefer CurrentControlSet - is 'CurrentControlSet' the devices currently connected?
  • likejudo
    likejudo about 11 years
    @robjb thanks for the link. Apparently it is not a dynamic listing. I connected two devices and after installing the driver, found both were in the CurrentControlSet. Then I disconnected one and did a search in the registry. I still found two listed in CurrentControlSet
  • shahar_m
    shahar_m about 11 years
    This information is indeed static and does not change even when the COM port is not connected, therefore not useful. +1.
  • Rob
    Rob almost 11 years
    I only needed to get the name of the device, not whether it was connected, so semi-static info was perfectly fine. Checking for connectivity was handled differently in my application, and wasn't part of this question.
  • bgplaya
    bgplaya over 9 years
    Hi guys, did anyone find a way to get if device is currently connected?
  • Ian M
    Ian M over 9 years
    A slight, helpful addition. For me (Win 8.1 x64), connected COMs are listed in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM under \Device\VCP0, \Device\VCP1, etc. I'm using FTDI COMs (xBee's), so I find the "friendly name" in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\ and compare it with the list of connected devices in there. Finding connected COMs could also be done using txrx library with a little more ease.
  • ZiglioUK
    ZiglioUK over 7 years
    Well, the link wasn't broken on Jun 30 2015 :-) web.archive.org/web/20150509122641/http://…
  • ZiglioUK
    ZiglioUK over 7 years
    What's wrong with accessing a static member of the class from a method of the same class? protected static List<DeviceInformation> infoObjects;