[英]Get drive letters of USB 3.0 devices (Java under Windows)
My Java program needs to get a list of the drive letters of connected USB devices, but only those that support USB 3.0 (both the device and the USB port it is plugged into, so that it works with high speed).
目前,我尝试通过执行 Java 程序的 PowerShell 命令来使用 WMI。
我已经找到了这个: Powershell: Grab USB Drive letter 。 但它也会列出 USB 2.0 设备。
关于版本检测,我发现: 如何检查可用 USB 端口的版本? - 我试过的 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 (链接)
我这里只从 USB 设备 realm 获取信息。 我可以加载设备并查看 VID&PID 和 bcdUSB 值,但无法将 map 用于驱动器和驱动器号。
lsusb 通过 Cygwin
根据这篇文章,linux 命令比 WMI 更容易处理。 所以我尝试在Windows下使用。 但我喜欢 usb4java 我只有 VID&PID + bcdUSB,而不是挂载点(驱动器号)。
搜索 Windows 注册表
我在 Windows 注册表中进行了一些字符串搜索。 没有成功。
读取 Windows 事件日志
我考虑过观察 Windows 事件以检测同时连接的驱动器和 USB 设备。 插入 USB 棒时我什至没有发现事件。
也许这就是您要查找的内容: 从 USB VID/PID 中查找可移动磁盘的 Windows 驱动器号至少有人将答案标记为工作... :-)
由于建议的链接为 C# 而不是 Java 解决了这个问题并省略了一步,因此我将在此处发布我的最终代码。
在 Java
bcdUSB=0x0300
通过 Powershell(使用jPowerShell )
Java class:
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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.