I am trying to do exactly what is being done over here: How do I GetModuleFileName() if I only have a window handle (hWnd)?
But in java instead of C#.
So far I have managed to this:
public static final int PROCESS_QUERY_INFORMATION = 0x0400;
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
int GetWindowThreadProcessId(HWND hwnd, IntByReference pid);
};
public interface Kernel32 extends StdCallLibrary {
Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class);
public Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);
public int GetTickCount();
};
public interface psapi extends StdCallLibrary {
psapi INSTANCE = (psapi)Native.loadLibrary("psapi", psapi.class);
int GetModuleFileNameExA (Pointer process, Pointer hModule, byte[] lpString, int nMaxCount);
};
public static String getModuleFilename(HWND hwnd)
{
byte[] exePathname = new byte[512];
Pointer zero = new Pointer(0);
IntByReference pid = new IntByReference();
User32.INSTANCE.GetWindowThreadProcessId(hwnd, pid);
System.out.println("PID is " + pid.getValue());
Pointer process = Kernel32.INSTANCE.OpenProcess(PROCESS_QUERY_INFORMATION, false, pid.getValue());
int result = psapi.INSTANCE.GetModuleFileNameExA(process, zero, exePathname, 512);
String text = Native.toString(exePathname).substring(0, result);
return text;
}
The window handle that is given is valid, and the PID is always printed successfully. "Process
" appears to return a value but the "result
" is always zero. Could anyone knowledgeable about JNA kindly show me where my mistake is?
EDIT: Finally, SUCCESS! The problem was this line (where the first value had to be 1040
):
Pointer process = Kernel32.INSTANCE.OpenProcess(1040, false, pid.getValue());
This may not be the reason it's failing, but I think the dwProcessId
parameter should be an int
, not IntByReference
.
See MSDN (http://msdn.microsoft.com/en-us/library/ms684320(v=VS.85).aspx):
HANDLE WINAPI OpenProcess(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in DWORD dwProcessId
);
It's just a regular DWORD.
Also, you can use GetLastError() to return more information about why the function call failed. Finally, this is a long shot, but your declaration of PROCESS_QUERY_INFORMATION
is not included in the code snippet -- make sure it has the correct value (0x0400).