通过JNA调用COM接口时出现无效的内存访问异常

时间:2016-07-04 12:29:29

标签: java com jna

我正在尝试隔离当我从JNA调用MS AutomationClient COM控件时遇到的问题。

我为整个库创建了一个处理程序:

  public static UIAutomationHandler create() {
    Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_APARTMENTTHREADED);
    PointerByReference pbr = new PointerByReference();
    WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(
            CLSID_CUIAutomation,
            null,
            WTypes.CLSCTX_SERVER,
            IID_IUIAutomation,
            pbr);
    COMUtils.checkRC(hr);
    UIAutomationHandler tb = new UIAutomationHandler(pbr.getValue());
    return tb;
  }

我编写了调用COM方法的方法(这是一个有效的例子):

public void GetRootElement(PointerByReference elt) {
    int result = this._invokeNativeInt(5, new Object[]{this.getPointer(), elt});
    COMUtils.checkRC(new WinNT.HRESULT(result));
}

当我调用CreateAndCondition方法时,它接受另外两个属性,并返回另一个属性,如下所示:

public void CreateAndCondition(Pointer condition0, Pointer condition1, PointerByReference condition) {

    int result = this._invokeNativeInt(25, new Object[]{this.getPointer(), condition0, condition1, condition});
    COMUtils.checkRC(new WinNT.HRESULT(result));
}

我已尽可能多地提取和简化以下代码..

PointerByReference pbr0 = new PointerByReference();
PointerByReference pbr1 = new PointerByReference();
PointerByReference pbr = new PointerByReference();

Variant.VARIANT var1 = new Variant.VARIANT.ByReference();
Variant.VARIANT var2 = new Variant.VARIANT.ByReference();

var2.setValue(Variant.VT_INT, ControlType.Window);
var1.setValue(Variant.VT_BSTR, sysAllocated);

this.handler.CreatePropertyCondition(PropertyID.Name.getValue(), var1, pbr0);
this.handler.CreatePropertyCondition(PropertyID.ControlType.getValue(), var2, pbr1);
this.handler.CreateAndCondition(pbr0.getPointer(), pbr1.getPointer(), pbr);

我得到以下堆栈跟踪:

Exception in thread "main" java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokeInt(Native Method)
    at com.sun.jna.Function.invoke(Function.java:386)
    at com.sun.jna.Function.invoke(Function.java:321)
    at com.sun.jna.Function.invoke(Function.java:276)
    at com.sun.jna.Function.invoke(Function.java:267)
    at com.sun.jna.Function.invokeInt(Function.java:674)
    at com.sun.jna.platform.win32.COM.COMInvoker._invokeNativeInt(COMInvoker.java:27)
    at mmarquee.automation.uiautomation.impl.UIAutomationHandler.CreateAndCondition(UIAutomationHandler.java:82)
    at mmarquee.automation.UIAutomation.getDesktopWindow(UIAutomation.java:205)
    at mmarquee.automation.TestMainWPF.run(TestMainWPF.java:57)
    at mmarquee.automation.MainWPF.main(MainWPF.java:23)

我已经为Delphi编写了这段代码的版本,并使用了com4jna库的旧版本,但这似乎让我失败了。

那么我做错了什么?

提前致谢

更新:我认为问题实际上在GetPropertyCondition的定义中,它接受Variant(如下所示)。

public void CreatePropertyCondition(int propertyId, Variant.VARIANT value, PointerByReference elt) {
        int result = this._invokeNativeInt(UIA_CREATE_PROPERTY_CONDITION, new Object[]{this.getPointer(), propertyId, value, elt});
        COMUtils.checkRC(new WinNT.HRESULT(result));
}

当我在返回的对象上使用QueryInterface时,我得到了同样的错误。所以它与通过COM编组变量有关。

1 个答案:

答案 0 :(得分:1)

有些问题是错误的,但调用代码看起来应该更像:

Variant.VARIANT.ByValue var1 = new Variant.VARIANT.ByValue();
Variant.VARIANT.ByValue var2 = new Variant.VARIANT.ByValue();

var2.setValue(Variant.VT_INT, ControlType.Window);
var1.setValue(Variant.VT_BSTR, sysAllocated);

this.handler.CreatePropertyCondition(PropertyID.Name.getValue(), var1, pbr0);
this.handler.CreatePropertyCondition(PropertyID.ControlType.getValue(), var2, pbr1);
this.handler.CreateAndCondition(pbr0.getValue(), pbr1.getValue(), pbr);

变量是ByValue而不是ByReferece,并且CreateAndCondition的输入是.getValue(),而不是.getPointer()