Getting device/driver information related to a COM port? Getting device/driver information related to a COM port? windows windows

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:

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


@robjb Your code does not allow for more than one device to be connected. How will the user know the device name? I added to your code thus to return a list of com ports:

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

Update: I don't think these are solutions. Why? This information is statically stored in the registry - even when the device is not connected.


Great example, using JNA, here.The author (Geir Arne Ruud) has released it under Public Domain License.

My example code

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