(将c#转换为Java JNA) - 来自hwnd的GetModuleFileName

时间:2011-09-22 21:24:03

标签: java winapi java-native-interface jna

我正在努力做到这里正在做的事情:How do I GetModuleFileName() if I only have a window handle (hWnd)?

但是在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());

2 个答案:

答案 0 :(得分:3)

这可能不是它失败的原因,但我认为dwProcessId参数应该是int,而不是IntByReference

请参阅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
);

这只是一个普通的DWORD。

此外,您可以使用GetLastError()返回有关函数调用失败原因的更多信息。最后,这是一个很长的镜头,但您的PROCESS_QUERY_INFORMATION声明未包含在代码段中 - 请确保它具有正确的值(0x0400)。

答案 1 :(得分:1)

为什么所有的麻烦都与进程id?

引用GetModuleFilename()的文件:

  

hModule [in,optional]:

     

正在请求路径的已加载模块的句柄。如果   此参数为NULL,GetModuleFileName检索该路径   当前进程的可执行文件。

如果你想要当前进程的模块fileName,只需传递NULL作为进程ID。

如果您需要其他进程的模块文件名,则在调用OpenProcess()之前需要特定的访问权限。 here描述了更改访问权限,并且很难实现(它需要大量的步骤来查找权限名称,获取权限的luid,调整权限的权限等)< / p>