我在我的Java应用程序中使用了各种Win32 API函数,并使用GetLastError
来获取有关API调用失败的信息。
大部分时间它都有效,但现在我找到了一个似乎重置上一个错误的情况。
这是我在Java应用程序和VB6应用程序中所做的事情:
GetModuleFileNameEx
。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);
}
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));
适用于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));
答案 0 :(得分:5)
documentation描述了两个选项:
如果函数设置系统错误属性(errno或GetLastError()),如果在JNA映射中声明异常,则错误代码将作为LastErrorException抛出。或者,您可以使用Native.getLastError()来检索它,前提是已使用true值调用Native.setPreserveLastError(boolean)。抛出异常是首选,因为它具有更好的性能。
调用GetLastError
的问题是JNA框架和Java运行时可能会调用Windows函数来重置错误。因此,您不应尝试直接致电GetLastError
。
答案 1 :(得分:1)
你可以使用"抛出LastErrorException"通常是有效的,但这并不总是最好的解决方案。测试API函数的返回值更安全,并在API函数的返回值指示发生错误时调用Native.getLastError()。
Native.getLastError()返回系统错误值的内部副本,该副本在JNA返回的最后一个API方法调用返回后立即存储(这在调用ffi_call()后在native/dispatch.c中完成)。错误值由JNA存储在线程本地存储中,并且Java运行时不能更改。它不再需要调用Native.setPreserveLastError(true),因为始终保留最后一个错误值。
如果"抛出LastErrorException"使用时,JNA在调度函数调用之前将系统错误值设置为0。通常,在系统API函数成功后该值为零,但没有明确的保证。
Linux程序员手册(man 3 errno)声明:" 只有当调用的返回值指示错误时(例如,大多数系统为-1),其值才有意义调用;大多数库函数中的-1或NULL);成功的功能可以改变errno。"
Wikipedia:" 任何库函数都可以在返回之前更改存储的值,无论它们是否检测到错误。"
在Windows下,GetLastError API函数的文档不保证API函数(记录为设置上一个错误代码)将其设置为0或成功时将其保留为0。