【问题标题】:How to I access the data of a WMI Query (via JNA) SAFEARRAY result如何访问 WMI 查询的数据(通过 JNA)SAFEARRAY 结果
【发布时间】:2019-04-12 12:25:11
【问题描述】:

我使用 jna 来运行 WMI 查询。 以下代码查询 WMI SELECT Caption,Capabilities from Win32_DiskDrive。 Win32_DiskDrive.Capabilities 的类型是 uint16[] 并且 result.getValue 返回一个 SAFEARRAY 实例。

System.out.println("Var Type(3 expected): " + value.getVarType().intValue());

如果我多次启动该过程,则随机返回 0 或 3。

System.out.println("Size (>0 expected): " + (value.getUBound(0) - value.getLBound(0)));

是正确的,但是

Object el = value.getElement(0);

失败。

value.accessData();

返回 null 这也是意外的,所以我不能使用 OaIdlUtil#toPrimitiveArray (Nullpointer)

不幸的是,代码不起作用,我不知道可能出了什么问题。有什么想法吗?

enum Win32_DiskDrive_Values {
        Caption,
        Capabilities
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        try {
            WmiQuery<Win32_DiskDrive_Values> serialNumberQuery = new WmiQuery<Win32_DiskDrive_Values>("Win32_DiskDrive", Win32_DiskDrive_Values.class);
            Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_MULTITHREADED);
            WmiResult<Win32_DiskDrive_Values> result = serialNumberQuery.execute();
            for (int i = 0; i < result.getResultCount(); i++) {
                System.out.println(result.getValue(Win32_DiskDrive_Values.Caption, i));
                SAFEARRAY value = (SAFEARRAY) result.getValue(Win32_DiskDrive_Values.Capabilities, i);
                // According to https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-diskdrive, the type of Capabilities
                // should be uint16[] which should be Variant.VT_I2 (2-byte integer)
                // however, it is not constant. sometimes it is 0, sometimes Variant.VT_I2 (3);
                System.out.println("Var Type(3 expected): " + value.getVarType().intValue());
                System.out.println("Size (>0 expected): " + (value.getUBound(0) - value.getLBound(0)));
                Object el = value.getElement(0);
                System.out.println("Element 0 (!=null expected): " + el);
                Pointer pointer = value.accessData();
                System.out.println("pointer (!=null expected): " + pointer);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            Ole32.INSTANCE.CoUninitialize();
        }
    }

【问题讨论】:

    标签: java wmi jna


    【解决方案1】:

    我提交给 JNA 项目的 WMI 代码仅用于处理原始值和字符串,而不是数组。您遇到的问题是 WMI 将指针地址返回到数组(VT_EMPTY = 0 的空数组或 VT_I4 = 3 的 32 位指针)。但是WMI结果是在迭代之后释放的,所以不能使用WmiResult来获取对象。

    您需要编写自己的代码(使用 JNA 实现作为起点)在迭代期间获取SAFEARRAY。您 asked this question on the JNA website 和 @matthiasblaesing 发布了以下适用于您的用例的 sn-p:

    public static void main(String[] args) throws IOException, InterruptedException {
        Ole32.INSTANCE.CoInitializeEx(null, Ole32.COINIT_MULTITHREADED);
    
        // Connect to the server
        Wbemcli.IWbemServices svc = WbemcliUtil.connectServer("ROOT\\CIMV2");
    
        // Send query
        try {
            Wbemcli.IEnumWbemClassObject enumerator = svc.ExecQuery("WQL", "SELECT Caption, Capabilities, CapabilityDescriptions FROM Win32_DiskDrive",
                    Wbemcli.WBEM_FLAG_FORWARD_ONLY | Wbemcli.WBEM_FLAG_RETURN_IMMEDIATELY, null);
    
            try {
                IWbemClassObject[] result;
                VARIANT.ByReference pVal = new VARIANT.ByReference();
                IntByReference pType = new IntByReference();
                IntByReference plFlavor = new IntByReference();
                while(true) {
                    result = enumerator.Next(0, 1);
                    if(result.length == 0) {
                        break;
                    }
                    COMUtils.checkRC(result[0].Get("Caption", 0, pVal, pType, plFlavor));
                    System.out.println("---------" + pVal.getValue() + "-------------");
                    OleAuto.INSTANCE.VariantClear(pVal);
                    COMUtils.checkRC(result[0].Get("CapabilityDescriptions", 0, pVal, pType, plFlavor));
                    SAFEARRAY safeArray = (SAFEARRAY) pVal.getValue();
                    for(int i = safeArray.getLBound(0); i<=safeArray.getUBound(0); i++) {
                        System.out.println("\t" + safeArray.getElement(i));
                    }
                    OleAuto.INSTANCE.VariantClear(pVal);
                    COMUtils.checkRC(result[0].Get("Capabilities", 0, pVal, pType, plFlavor));
                    safeArray = (SAFEARRAY) pVal.getValue();
                    for(int i = safeArray.getLBound(0); i<=safeArray.getUBound(0); i++) {
                        System.out.println("\t" + safeArray.getElement(i));
                    }
                    OleAuto.INSTANCE.VariantClear(pVal);
                    result[0].Release();
                }
            } finally {
                // Cleanup
                enumerator.Release();
            }
        } finally {
            // Cleanup
            svc.Release();
        }
    
        Ole32.INSTANCE.CoUninitialize();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      相关资源
      最近更新 更多