Java 获取与COM端口相关的设备/驱动程序信息?
我有一个串行到USB设备,在Windows设备管理器中有一个类似命名的设备驱动程序。设备在系统引导时并不总是获取相同的COM端口,因此我的程序需要在启动时识别它 我尝试使用枚举系统上的COM端口,但这不起作用,因为Java 获取与COM端口相关的设备/驱动程序信息?,java,windows,serial-port,device-driver,Java,Windows,Serial Port,Device Driver,我有一个串行到USB设备,在Windows设备管理器中有一个类似命名的设备驱动程序。设备在系统引导时并不总是获取相同的COM端口,因此我的程序需要在启动时识别它 我尝试使用枚举系统上的COM端口,但这不起作用,因为CommPortIdentifier.getName()只返回COM名称(如COM1、COM2等)。我需要获取驱动程序制造商名称或设备管理器中显示的驱动程序名称,并将其与COM名称关联 这在Java中很容易做到吗?(我对任何支持此功能的第三方Java库都感兴趣。)否则,我如何开始通过w
CommPortIdentifier.getName()
只返回COM名称(如COM1、COM2等)。我需要获取驱动程序制造商名称或设备管理器中显示的驱动程序名称,并将其与COM名称关联
这在Java中很容易做到吗?(我对任何支持此功能的第三方Java库都感兴趣。)否则,我如何开始通过win32 API实现这一点?我通过使用中David提供的
WinRegistry
类从与USB设备关联的注册表项中获取FriendlyName,实现了我想要的功能。然后,我从友好名称中解析出COM编号
需要考虑的一些事项:
HKEY\U LOCAL\U MACHINE\SYSTEM\CurrentControlSet\Enum\USB\
(在WinXP、Win7上测试)VID_xxxx&PID_xxxx
),因为VID和PID是特定于设备的,所以该密钥应在多个系统中可靠VID_xxxx&PID_xxxx
键包含另一个带有设备值的子键。我在使用WinRegistry
枚举子项时遇到了一些问题,因此在开发过程中,我对子项名称进行了硬编码,作为一种快速攻击。一个更安全的解决方案是搜索子键以找到正确的名称@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)));
}
}
ArrayList subKeys=WinRegistry.readStringSubKeys(WinRegistry.HKEY\u LOCAL\u MACHINE,keyPath);
ArrayList comPorts=新的ArrayList();
for(字符串子键:子键){
字符串friendlyName=getFriendlyName(键路径+子键);
if(friendlyName!=null&&friendlyName.contains(“MyDriverName”)&&friendlyName.contains(“COM”)){
int beginIndex=friendlyName.indexOf(“COM”)+3/*长度为'COM'*/;
int-endIndex=friendlyName.indexOf(“)”;
add(Integer.parseInt(friendlyName.substring(beginIndex,endIndex));
}
}
更新:我不认为这些是解决方案。为什么?此信息静态存储在注册表中,即使设备未连接。很好的示例,使用JNA。
作者(盖尔·阿恩·路德)已根据公共领域许可证发布了它
没有办法简单地获取连接到该com端口的设备的驱动程序名吗?@Anil请查看我从
getComNumber()
重构出来的getFriendlyName()
方法。不幸的是,友好名称并不总是那么友好。假设COM端口只有一个位数。。。坏了@robjb查看我的xp注册表,我看到usb设备列在ControlSet003和CurrentControlSet中。有什么理由选择CurrentControlSet?CurrentControlSet是当前连接的设备吗?@robjb感谢您的链接。显然,这不是一个动态列表。我连接了两个设备,安装驱动程序后,发现它们都在CurrentControlSet中。然后我断开一个,在注册表中搜索。我仍然发现CurrentControlSet中列出了两个此信息实际上是静态的,即使COM端口未连接,也不会更改,因此没有用处+1.我只需要知道设备的名称,而不需要知道它是否已连接,所以半静态信息非常好。在我的应用程序中,连接检查的处理方式有所不同,这不是问题的一部分。那么,链接在2015年6月30日没有断开:-)从同一类的方法访问该类的静态成员有什么问题?受保护的静态列表对象;
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;
}
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)));
}
}
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;
}