java.lang.UnsatifiedLinkError:查找函数时出错';GetModuleFileNameEx';

java.lang.UnsatifiedLinkError:查找函数时出错';GetModuleFileNameEx';,java,winapi,dll,jna,unsatisfiedlinkerror,Java,Winapi,Dll,Jna,Unsatisfiedlinkerror,我正在尝试在java应用程序中导入。该功能的定义是: DWORD WINAPI GetModuleFileNameEx( _In_ HANDLE hProcess, _In_opt_ HMODULE hModule, _Out_ LPTSTR lpFilename, _In_ DWORD nSize ); 我把它翻译成: public abstract DWORD GetModuleFileNameEx( WinNT.HANDLE hPro

我正在尝试在java应用程序中导入。该功能的定义是:

DWORD WINAPI GetModuleFileNameEx(
  _In_     HANDLE  hProcess,
  _In_opt_ HMODULE hModule,
  _Out_    LPTSTR  lpFilename,
  _In_     DWORD   nSize
);
我把它翻译成:

public abstract DWORD GetModuleFileNameEx(
    WinNT.HANDLE hProcess,
    WinNT.HMODULE hModule,
    char[] pathName,
    WinNT.DWORD pathNameSize
);
我在课堂上这样定义:

 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
 import com.sun.jna.platform.win32.Kernel32;
 import com.sun.jna.platform.win32.WinDef;
 import com.sun.jna.platform.win32.WinNT;
 import com.sun.jna.win32.W32APIOptions;


 public abstract interface Kernel32Ext
   extends Kernel32
 {
   public static final Kernel32Ext INSTANCE = (Kernel32Ext)Native.loadLibrary("kernel32.dll", Kernel32Ext.class, W32APIOptions.DEFAULT_OPTIONS);
   public abstract DWORD GetModuleFileNameEx(WinNT.HANDLE hProcess, WinNT.HMODULE hModule, char[] pathName, WinNT.DWORD pathNameSize);
 }
但是当我尝试调用该方法时,我得到一个错误:

java.lang.UnsatisfiedLinkError: Error looking up function 'GetModuleFileNameEx': Uvedená procedura nebyla nalezena.
我仔细检查了一下,根据这里关于堆栈溢出和其他JNA程序的帖子,
LPTSTR
在JNAAPI中正确地转换为
char[]
。因此,肯定还有其他问题。我是导入了错误的dll,还是使用了错误的选项


我在Windows 7 x64位(捷克语,因此出现非英语错误消息)上运行此函数。

在内核32(或其他地方)中没有该名称的函数。有关详细信息,请参阅MSDN页面。您要查找的函数是
GetModuleFileNameExW

好的,完整代码:

import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.W32APIOptions;

public interface Psapi extends WinNT {
    public static final Psapi INSTANCE = (Psapi)Native.loadLibrary("Psapi.dll", Psapi.class, W32APIOptions.DEFAULT_OPTIONS);
    public abstract WinDef.DWORD GetModuleFileNameExW(WinNT.HANDLE hProcess, WinNT.HMODULE hModule, char[] pathName, WinNT.DWORD pathNameSize);
}
注意,我最终从Psapi.dll而不是Kernel32.dll导入了函数

示例用法,获取给定窗口HWND的进程文件名:

  protected WinDef.HWND hwnd;
  @Override
  public String getProcessName() {
    // Refference to int that will later be filled 
    IntByReference pid = new IntByReference(0); 
    // This function gives pid number to the second parameter passed by refference
    UserExt.GetWindowThreadProcessId(hwnd, pid);
    // Now get handle to the process 
    // 0x0400 | 0x0010 stands for reading info
    // if you pass 0 you will get error 5 which stands for access denied
    int pidVal = pid.getValue();
    HANDLE process = Kernel32.INSTANCE.OpenProcess(0x0400 | 0x0010, false, pidVal);
    if(process==null)
      throw new APIException("Winapi error: "+(Kernel32.INSTANCE.GetLastError()));
    // Prepare buffer for characters, just as you would 
    // in goold 'ol C program
    char[] path = new char[150];
    DWORD buffSize = new DWORD(path.length);
    // The W at the end of the function name stands for WIDE - 2byte chars
    Psapi.INSTANCE.GetModuleFileNameExW(process, null, path, buffSize);
    // convert buffer to java string
    return String.copyValueOf(path);
  }

导出的函数是GetModuleFileNameExW。这是一个Unicode变量,作为注释与JavaChar[]匹配;我检查了自己的kernel32,它似乎缺少
GetModuleFileNameExW
(在Windows 10上),但是,加载psapi和KernelBase一样有效。相同的Java参数类型,只是不同的名称和dll。@jorn这都是documentedIt导入,但我必须从Psapi.dll导入。
W32API选项。默认的\u选项
包括一个函数名映射器,它解释了
-a
-W
后缀。通常,明确指出
-A
-W
是不合适的;只有在函数签名不同的情况下(通常围绕字符数组类型的用法)才应该这样做。