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 bu开发者_如何学Got 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).
why all the hassle with the process id ??
quoting from the documention of GetModuleFilename()
:
hModule [in, optional]:
A handle to the loaded module whose path is being requested. If this parameter is NULL, GetModuleFileName retrieves the path of the executable file of the current process.
if you want the module fileName of the current process, just pass NULL
as the process id.
if you want the module filename of another process, you need specific access rights before calling OpenProcess()
. changing the access rights is described here, and is quite difficult to achieve (it requires a great amount of steps to lookup the privilege name, get the luid of the privilege, adjust the privileges of the token, etc.)
精彩评论