(将 c# 转换为 Java JNA) - 从 hwnd GetModuleFileName
我正在尝试准确地执行这里所做的操作: 如果我只有一个窗口句柄 (hWnd),我该如何 GetModuleFileName()?
但是是在 java 而不是 C# 中。
到目前为止,我已经做到了这一点:
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;
}
给定的窗口句柄是有效的,并且 PID 始终打印成功。 “Process
”似乎返回一个值,但“result
”始终为零。任何了解 JNA 的人都可以告诉我我的错误在哪里吗?
编辑:最后,成功!问题出在这一行(其中第一个值必须是1040
):
Pointer process = Kernel32.INSTANCE.OpenProcess(1040, false, pid.getValue());
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());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能不是它失败的原因,但我认为 dwProcessId 参数应该是 int,而不是 IntByReference。
请参阅 MSDN (http://msdn.microsoft.com/en-us/library/ms684320(v=VS.85).aspx):
它只是一个常规的 DWORD。
另外,您可以使用 GetLastError( ) 返回有关函数调用失败原因的更多信息。最后,这是一个不太可能的情况,但是您的
PROCESS_QUERY_INFORMATION
声明未包含在代码片段中 - 请确保它具有正确的值 (0x0400)。This may not be the reason it's failing, but I think the
dwProcessId
parameter should be anint
, notIntByReference
.See MSDN (http://msdn.microsoft.com/en-us/library/ms684320(v=VS.85).aspx):
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).为什么进程 ID 这么麻烦?
引用
GetModuleFilename()
:
如果您想要当前进程的模块文件名,只需传递
NULL
作为进程ID。如果您想要另一个进程的模块文件名,则在调用
OpenProcess()
之前需要特定的访问权限。 此处介绍了如何更改访问权限,实现起来相当困难(需要大量的步骤来查找权限名称、获取权限的luid、调整token的权限等)why all the hassle with the process id ??
quoting from the documention of
GetModuleFilename()
: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.)