简体   繁体   English

在 Windows Java 中检查 USB 驱动器的文件系统完整性

[英]Checking filesystem integrity of USB drive in Windows Java

Our application involves an external device that mounts as a USB mass storage device.我们的应用程序涉及安装为 USB 大容量存储设备的外部设备。 I need to be able to check the integrity of that USB mass storage device from a Java application, running on Windows.我需要能够从在 Windows 上运行的 Java 应用程序检查 USB 大容量存储设备的完整性。

Currently I execute "chkdsk", which works fine unless the user's computer isn't configured for English.目前我执行“chkdsk”,除非用户的计算机没有配置为英语,否则它工作正常。 (Because I need to examine the chkdsk output to determine the state of the drive.) And, surprise, surprise, not every computer in the world is configured for English! (因为我需要检查 chkdsk output 以确定驱动器的 state。)而且,令人惊讶的是,并非世界上每台计算机都配置为英语!

There is a Win32 class called "Win32_Volume" with a method called "Chkdsk" that is just what I'm looking for.有一个名为“Win32_Volume”的 Win32 class 和一个名为“Chkdsk”的方法,这正是我正在寻找的。

I need to call it from Java, and JNA seems the way to go.我需要从 Java 调用它,而 JNA 似乎是通往 go 的方式。

How can I use COM to call a method from a Win32 WMI class?如何使用 COM 从 Win32 WMI class 调用方法?

You can send an FSCTL_IS_VOLUME_DIRTY message using DeviceIoControl .您可以使用DeviceIoControl发送FSCTL_IS_VOLUME_DIRTY消息。

Here is and example of calling DeviceIoControl. 是调用 DeviceIoControl 的示例。

Or you can use WMI, both the the Win32_Volume and the Win32_LogicalDisk class expose a DirtyBitSet property.或者您可以使用 WMI, Win32_VolumeWin32_LogicalDisk class 都公开了DirtyBitSet属性。 However WMI is really inteded for scripting languages and is not preferred because of it's incredible performance overhead.然而,WMI 确实适用于脚本语言,并且由于其令人难以置信的性能开销而不是首选。

The Win32_Volume documentation with the Chkdsk method you cite indicates it is a legacy API, but has not yet been deprecated so you could use it.您引用的带有Chkdsk方法的Win32_Volume 文档表明它是旧版 API,但尚未被弃用,因此您可以使用它。

The current Storage Management API equivalent is MSFT_Volume .当前的存储管理 API 等效为MSFT_Volume It has a Diagnose method that looks to perform similar functionality.它有一个看起来执行类似功能的Diagnose方法。

To execute a method on a WMI object via COM you need to obtain a pointer to a WbemServices object.要通过 COM 在 WMI object 上执行方法,您需要获取指向WbemServices object 的指针。 It has an ExecMethod method you can invoke that does what you want for WMI classes.它有一个ExecMethod方法,您可以调用它来为 WMI 类执行您想要的操作。 The code to retrieve this object is in JNA's WbemcliUtil class as a return type from the connectServer() method.检索此 object 的代码位于 JNA 的 WbemcliUtil class 中,作为connectServer()方法的返回类型。

You will also need the full path to the Class Object;您还需要 Class Object 的完整路径; this is available by querying WMI for the __PATH , similarly to how you'd query any other field.这可以通过查询 WMI 的__PATH来获得,类似于查询任何其他字段的方式。 That same WbemcliUtil class has a WmiQuery class you can instantiate to execute the query, collecting that path from the WmiResult .同样的WbemcliUtil class 有一个WmiQuery class 您可以实例化以执行查询,从WmiResult收集该路径。 See the JNA test classes for examples on using these.有关使用这些的示例,请参阅 JNA 测试类。

Finally, you can execute the WMI method.最后,您可以执行 WMI 方法。 The code below will accomplish it for String properties, eg, the MSFT_StorageDiagnoseResult object you'd get from MSFT_Volume 's Diagnose method.下面的代码将为字符串属性完成它,例如,您从MSFT_VolumeDiagnose方法中获得的MSFT_StorageDiagnoseResult object。 You'd have to treat other return types differently.您必须以不同的方式对待其他返回类型。

/**
 * Convenience method for executing WMI methods without any input parameters
 * 
 * @param svc
 *            The WbemServices object
 * @param clsObj
 *            The full path to the class object to execute (result of WMI
 *            "__PATH" query)
 * @param method
 *            The name of the method to execute
 * @param properties
 *            One or more properties returned as a result of the query
 * @return An array of the properties returned from the method
 */
private static String[] execMethod(WbemServices svc, String clsObj, String method, String... properties) {
    List<String> result = new ArrayList<>();
    PointerByReference ppOutParams = new PointerByReference();
    HRESULT hres = svc.ExecMethod(new BSTR(clsObj), new BSTR(method), new NativeLong(0L), null, null, ppOutParams,
            null);
    if (COMUtils.FAILED(hres)) {
        return new String[0];
    }
    WbemClassObject obj = new WbemClassObject(ppOutParams.getValue());
    VARIANT.ByReference vtProp = new VARIANT.ByReference();
    for (String prop : properties) {
        hres = obj.Get(new BSTR(prop), new NativeLong(0L), vtProp, null, null);
        if (!COMUtils.FAILED(hres)) {
            result.add(vtProp.getValue() == null ? "" : vtProp.stringValue());
        }
    }
    obj.Release();
    return result.toArray(new String[result.size()]);
}

A more complete example of querying a COM object, where I extracted the above code, is in this utility class which queries the GetOwner() and GetOwnerSid() methods on the Win32_Process object. A more complete example of querying a COM object, where I extracted the above code, is in this utility class which queries the GetOwner() and GetOwnerSid() methods on the Win32_Process object. It's legacy code from before I contributed the WbemCli class to JNA, so you'll have to adapt some of it, but it should be a good starting point.这是我将WbemCli class 贡献给 JNA 之前的遗留代码,因此您必须对其进行一些调整,但这应该是一个很好的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM