Getting device/driver information related to a COM port?
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:
USB devices are located at
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\
in the registry (tested on WinXP, Win7.)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.The
VID_xxxx&PID_xxxx
key contains another sub-key with device values. I had some trouble enumerating the sub-keys withWinRegistry
, 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.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;
}
Comments
-
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 about 11 yearsIs there no way to simply get the driver name for the device connected to that com port?
-
Rob about 11 years@Anil Check out the
getFriendlyName()
method I've refactored out fromgetComNumber()
. Unfortunately the friendly name isn't always that friendly. -
Ben Voigt about 11 yearsAssuming that a COM port is only a single digit... broken!
-
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 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 about 11 yearsThis information is indeed static and does not change even when the COM port is not connected, therefore not useful. +1.
-
Rob almost 11 yearsI 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 over 9 yearsHi guys, did anyone find a way to get if device is currently connected?
-
Ian M over 9 yearsA 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 over 7 yearsWell, the link wasn't broken on Jun 30 2015 :-) web.archive.org/web/20150509122641/http://…
-
ZiglioUK over 7 yearsWhat's wrong with accessing a static member of the class from a method of the same class? protected static List<DeviceInformation> infoObjects;