1

在将其他几个标头映射Vss.h到 Java/JNA 之后(请参阅此问题),我正在尝试运行一些 COM 对象方法并在调试它们时遇到问题。

我不知道我调用的是正确的方法还是具有类似参数的方法。我在此处的 JNA 文档中找到了一些错误代码,但它不包括我看到的所有错误。

一些例子:

// gather writer metadata
public int GatherWriterMetadata(IVssAsync pAsync)
{
    return _invokeNativeInt( 5, new Object[] { getPointer(), pAsync });
}

我有错误-2147212542

为了

// Called to set the context for subsequent snapshot-related operations
public int SetContext(WinDef.LONG lContext)
{
    return _invokeNativeInt( 32, new Object[] { getPointer(), lContext });
}

我有 java.lang.Error: Invalid memory access at com.sun.jna.Native.invokeInt(Native Method)

我尝试为 SetContext 方法使用像 31,32 和 33 这样的数字。

4

1 回答 1

0

不要尝试“玩数字”,因为您可能会遇到随机行为。

正如我在回答您的其他问题时提到的,调用的整vtblId数值_invokeNative...必须来自Vtbl头文件中的结构。我没有直接访问头文件的权限,但是这个来自 Rust的映射可能很好用,但是由于这个接口(和所有 COM 接口)扩展IUnknown了,它已经包含了函数QueryInterface()AddRef()Release(),它们的vtblId 值都是 0, 1 和 2

您的GatherWriterMetadata方法使用vtblId5,实际上是在调用InitializeForBackup()函数,该函数需要一个BSTR参数。你给它一些其他参数,所以它返回一个错误。(如果通过十进制值 -2147212542 查找错误不起作用,您可以转换为二进制补码十六进制,在这种情况下是0x80042302系统还原错误。)

根据我的计数,您应该使用vtblId9 表示GatherWriterMetadata. 请自己数数确认。

根据我的计算,您的SetContext方法应该是使用vtblId35。再次,请计算函数的数量(从 3 开始)以自己确认。

另外,我看到您使用 int 类型作为大多数这些函数的返回类型,而不是HRESULT. 由于HRESULT最终是 32 位整数类型,因此这将起作用。但是,如果您实际上将HRESULT其用作返回值,则可以访问更方便/自我记录的错误处理方法,例如COMUtils.SUCCEEDED()and COMUtils.FAILED(),甚至是在失败时COMUtils.checkRC()抛出格式良好的方法。COMException

所以你的映射应该是:

// gather writer metadata
public HRESULT GatherWriterMetadata(IVssAsync pAsync)
{
    return _invokeNativeObject( 9,
        new Object[] { getPointer(), pAsync }, HRESULT.class);
}

// Called to set the context for subsequent snapshot-related operations
public HRESULT SetContext(WinDef.LONG lContext)
{
    return _invokeNativeObject( 35,
        new Object[] { getPointer(), lContext }, HRESULT.class);
}

顺便说一句,由于 WindowsLONG类型始终为 32 位,您还可以将第二个映射简化为:

public HRESULT SetContext(int lContext) { ... }
于 2020-07-26T20:02:57.643 回答