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

在大多数情况下,它都可以工作,但是现在我发现了一种情况,似乎有些东西可以重置最后一个错误。

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

  • 我使用PID 4(系统)打开进程的句柄
  • 我使用该句柄调用 GetModuleFileNameEx
  • 我使用该句柄调用 GetProcessImageFileName

  • 现在,两个API函数均按预期失败(它们返回零),并且在我的VB6应用程序中,两个API调用之后GetLastError返回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));
    

    最佳答案

    documentation描述了两个选项:

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

    调用GetLastError的问题在于JNA框架以及Java运行时实际上可能调用Windows函数来重置错误。因此,您不应尝试直接调用GetLastError

    09-10 06:39
    查看更多