如何使GetLastError可靠地与JNA一起使用?

Dan*_*ski 1 java winapi jna

我在我的Java应用程序中使用了各种Win32 API函数,我用它GetLastError来获取有关API调用失败的信息.

它大部分时间都有效,但现在我发现了一个似乎重置上一个错误的情况.

这是我在Java应用程序和VB6应用程序中所做的事情:

  1. 我用PID 4(系统)打开过程的句柄
  2. 我打电话GetModuleFileNameEx给那个把柄.
  3. 我打电话GetProcessImageFileName给那个把柄.

现在两个 API函数都按预期失败(它们返回零),并且在我的VB6应用程序中,GetLastError在两个API调用之后返回87("无效参数").

但是在我的Java应用程序中,只有在GetModuleFileNameEx最后一个错误设置为87之后.GetProcessImageFileName它始终为零.

我该怎么办?

编辑:

以下是JNA声明:

public interface PsApi extends StdCallLibrary {
    PsApi INSTANCE = (PsApi) Native.loadLibrary("psapi", PsApi.class, 
            W32APIOptions.UNICODE_OPTIONS);
    int GetModuleFileNameEx(WinNT.HANDLE hProcess, WinDef.HMODULE hModule, 
            char[] lpFilename, int nSize);
    int GetProcessImageFileName(WinNT.HANDLE hProcess, char[] lpImageFileName, 
            int nSize);
}
Run Code Online (Sandbox Code Playgroud)

和调用代码 GetProcessImageFileName

char[] buffer = new char[2048];
int result = PsApi.INSTANCE.GetProcessImageFileName(hProcess, buffer, 
   buffer.length);
if (result == 0) {
    throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return new String(Arrays.copyOf(buffer, result));
Run Code Online (Sandbox Code Playgroud)

并为 GetModuleFileNameEx

char[] buffer = new char[2048];
int result = PsApi.INSTANCE.GetModuleFileNameEx(hProcess, hModule, buffer,
    buffer.length);
if (result == 0) {
     throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return new String(Arrays.copyOf(buffer, result));
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

文档描述了两个选项:

如果函数设置系统错误属性(errno或GetLastError()),如果在JNA映射中声明异常,则错误代码将作为LastErrorException抛出.或者,您可以使用Native.getLastError()来检索它,前提是已使用true值调用Native.setPreserveLastError(boolean).抛出异常是首选,因为它具有更好的性能.

调用的问题GetLastError是JNA框架和Java运行时可能会调用Windows函数来重置错误.所以你不应该试图GetLastError直接打电话.