我的 Java 程序需要获取已连接 USB 设备的驱动器盘符列表,但仅限于支持 USB 3.0 的设备(设备及其插入的 USB 端口,以便高速运行)。< /p>
目前,我尝试通过 Java 程序执行的 PowerShell 命令来使用 WMI。
我已经找到了:Powershell: Grab USB Drive letter。但它也会列出 USB 2.0 设备。
关于版本检测,我发现:How to check the version of the available USB ports? - 我尝试的 PowerShell 命令是 Get-WmiObject Win32_USBHub
。这带来了几个问题。第一:它列出的东西远不止 USB 驱动器(我认为还有我 PC 的所有 USB 集线器)。第二:即使列表中的所有项目都有一个 USBVersion 字段,但它始终为空。
我最近几天研究的本质是,我需要连接两个领域的信息。
对于给定的驱动器号,我需要找到 bcdUSB 值。但是我还没有找到获取USB设备对应的驱动器的方法。
WMI over PowerShell
我发现的相关命令是
Get-Disk // Get BusType
gwmi Win32_LogicalDisk // Get drive letter
// Those make the connection between disk and logical disk
gwmi Win32_LogicalDiskToPartition
gwmi Win32_LogicalDiskToPartition
即使我得到了 BusType,我也无法连接到 bcdUSB
usb4java (Link)
我在这里只从 USB 设备领域获取信息。我可以加载设备并查看 VID&PID 和 bcdUSB 值,但无法将其映射到驱动器和驱动器号。
lsusb 通过 Cygwin
根据this post,linux 命令比WMI 更容易处理。所以我尝试在Windows下使用它。但是我喜欢usb4java我只有VID&PID+bcdUSB,没有挂载点(盘符)。
搜索 Windows 注册表
我在 Windows 注册表中进行了一些字符串搜索。没有成功。
读取 Windows 事件日志
我想过监视 Windows 事件以检测同时连接的驱动器和 USB 设备。插入 U 盘时我什至没有发现事件。
答案 0 :(得分:1)
也许这就是你要找的: Find Windows Drive Letter of a removable disk from USB VID/PID 至少有人将答案标记为有效... :-)
答案 1 :(得分:0)
由于建议的链接为 C# 而非 Java 解决了这个问题并且省略了一个步骤,我将在此处发布我的最终代码。
在 Java 中
bcdUSB=0x0300
的 USB 设备通过 Powershell(使用 jPowerShell)
Java 类:
class UsbDetector {
private PowerShell shell;
@PostConstruct
private void init() {
shell = com.profesorfalken.jpowershell.PowerShell.openSession();
}
@OnDestroy
private void onShutdownHook() {
shell.close();
}
/**
* Get drive letters of USB 3.0 devices.
*/
public List<String> getDriveLettersForUsb3Devices() throws IOException, UsbException {
List<UsbDevice> devicesUSB3 = getAllUsb3Devices();
ImmutableList.Builder<String> driveLetterList = ImmutableList.builder();
for (UsbDevice device : devicesUSB3) {
String vidAndPid = getVidAndPid(device);
String powerShellScript = buildScript(vidAndPid);
String driveLetter = executeOnPowerShell(powerShellScript);
driveLetterList.add(driveLetter);
}
return driveLetterList.build();
}
private String executeOnPowerShell(String powerShellScript) {
InputStream psScriptStream = new ByteArrayInputStream(powerShellScript.getBytes());
BufferedReader psScriptReader = new BufferedReader(new InputStreamReader(psScriptStream));
PowerShellResponse response = shell.executeScript(psScriptReader);
return response.getCommandOutput();
}
private String buildScript(String vidAndPid) throws IOException {
InputStream psScriptStream =
getClass().getClassLoader().getResourceAsStream("GetUsbDrives.ps1");
String psScript = IOUtil.toString(psScriptStream);
psScript = String.format("$input=\"%s\"", vidAndPid) + "\n" + psScript;
return psScript;
}
/**
* The Vendor ID and Product ID are necessary to find the device via WMI.
*/
private String getVidAndPid(UsbDevice device) {
short vendorId = device.getUsbDeviceDescriptor().idVendor();
short productId = device.getUsbDeviceDescriptor().idProduct();
String vendorIdHexString = String.format("%04x", vendorId).toUpperCase();
String productIdHexString = String.format("%04x", productId).toUpperCase();
String vidAndPid = String.format("VID_%s&PID_%s", vendorIdHexString, productIdHexString);
return vidAndPid;
}
/**
* From all Usb devices find those with USB 3.0. The value bcdUsb is a hexadecimal coded number
* telling us the USB version.
*/
private List<UsbDevice> getAllUsb3Devices() throws UsbException {
List<UsbDevice> devicesUSB3 = Lists.newArrayList();
UsbServices services = new org.usb4java.javax.Services();
UsbHub hub = services.getRootUsbHub();
List<UsbDevice> devices = getAllUsbDevices(hub);
for (UsbDevice device : devices) {
UsbDeviceDescriptor descriptor = device.getUsbDeviceDescriptor();
short bcdUsb = descriptor.bcdUSB();
String bcdDecoded = DescriptorUtils.decodeBCD(bcdUsb);
if (Objects.equal(bcdDecoded, "3.00")) {
devicesUSB3.add(device);
}
}
return devicesUSB3;
}
/**
* UsbHubs can either mount UsbDevices or further UsbHubs. This method searches through the tree
* of UsbHubs for UsbDevices and returns them as list.
*/
private List<UsbDevice> getAllUsbDevices(UsbHub hub) {
List<UsbDevice> devices = Lists.newArrayList();
List<UsbDevice> attachedDevices = hub.getAttachedUsbDevices();
for (UsbDevice device : attachedDevices) {
if (device instanceof UsbHub) {
List<UsbDevice> subdevices = getAllUsbDevices((UsbHub) device);
devices.addAll(subdevices);
} else {
devices.add(device);
}
}
return devices;
}
}
PowerShell 脚本:
# $input = "VID_XXXX&PID_XXXX (this line is added in Java Code)
# For given VID and PID of a USB device we search for
# the corresponding logical disk to get the drive letter.
# The chain of objects is:
# PnPEntity (PnP = Plug and Play)
# -> USBController
# -> Some associator of USBController that has a related disk drive
# -> diskDrive
# -> diskPartition
# -> logicalDisk
# Find PnPEntity for given VID and PID
$usbPnPEntity = (gwmi Win32_PnPEntity | where DeviceID -match $input)
# Get USB Controller related to PnP Entity
$usbController = $usbPnPEntity.getRelated("Win32_USBController")
$usbControllerID = $usbController.DeviceID
# Find objects associated with the USB Controller
$query = "ASSOCIATORS OF {Win32_USBController.DeviceID='$usbControllerID'}"
$associators = ([wmisearcher]$query).get()
# Search through associators
foreach ($associator in $associators) {
# Find associator that is related to a disk Drive
$assoDeviceID = $associator.DeviceID
$diskDrive = (gwmi win32_diskdrive | where PNPDeviceID -eq $assoDeviceID)
if($diskDrive){
# Get logical Disk related to the disk drive
$logicalDisk = $diskDrive.getRelated("Win32_DiskPartition").getRelated("Win32_LogicalDisk")
# Print device ID which is the drive letter (e.g. "C:")
$logicalDisk.DeviceID
break
}
}
Maven 依赖:
<dependency>
<groupId>org.usb4java</groupId>
<artifactId>usb4java-javax</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.profesorfalken</groupId>
<artifactId>jPowerShell</artifactId>
<version>3.1.1</version>
</dependency>