2017-05-06 8 views
2

J'essaie d'importer GetModuleFileNameEx dans une application java. La définition de la fonction est:java.lang.UnsatisfiedLinkError: Erreur lors de la recherche de la fonction 'GetModuleFileNameEx'

DWORD WINAPI GetModuleFileNameEx(
    _In_  HANDLE hProcess, 
    _In_opt_ HMODULE hModule, 
    _Out_ LPTSTR lpFilename, 
    _In_  DWORD nSize 
); 

Je traduit cela en:

public abstract DWORD GetModuleFileNameEx(
    WinNT.HANDLE hProcess, 
    WinNT.HMODULE hModule, 
    char[] pathName, 
    WinNT.DWORD pathNameSize 
); 

qui je définissais en classe comme ceci:

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); 
} 

Mais quand je tente d'appeler la méthode que je obtenir une erreur:

java.lang.UnsatisfiedLinkError: Error looking up function 'GetModuleFileNameEx': Uvedená procedura nebyla nalezena. 

ouble vérifié et selon les messages ici sur le débordement de la pile et d'autres programmes JNA, LPTSTR traduit correctement à char[] dans l'API JNA. Donc, il doit y avoir quelque chose d'autre qui ne va pas. Est-ce que j'importe la mauvaise DLL, ou avec de mauvaises options?

Je cours cela sur Windows 7 x 64 bits (tchèque, d'où le message d'erreur non-anglais).

+1

La fonction exportée est GetModuleFileNameExW. C'est la variante Unicode correspondant java char [] –

+0

Comme une note; J'ai vérifié mon propre noyau32, et il semble manquer 'GetModuleFileNameExW' (sur Windows 10), cependant, le chargement de psapi fonctionne, ainsi que KernelBase. Les mêmes types de paramètres Java, juste un nom et une DLL différents. –

+0

@jorn tout est documenté –

Répondre

1

Il n'y a pas de fonction de ce nom dans kernel32 (ou ailleurs). Voir la page MSDN pour GetModuleFileNameEx. La fonction que vous cherchez est GetModuleFileNameExW.

+0

Il importe comme ça correctement, mais j'ai dû importer à partir de Psapi.dll à la place. –

+0

'W32APIOptions.DEFAULT_OPTIONS' inclut un mappeur de nom de fonction qui prend en compte les suffixes' -A' et '-W'. Normalement, il est inapproprié d'indiquer explicitement '-A' ou' -W'; cela ne devrait être fait que lorsque la signature de la fonction serait différente (généralement autour des utilisations des types de tableaux de caractères). – technomage

0

Ok, le code complet:

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); 
} 

Notez que j'ai fini par importer la fonction de Psapi.dll, non Kernel32.dll.

Exemple d'utilisation, pour obtenir le nom de fichier d'un processus donné une fenêtre 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); 
    }