2011-09-22 64 views
1

GetModuleFileName我想在這裏做的正是正在做什麼:How do I GetModuleFileName() if I only have a window handle (hWnd)?(轉換C#與Java JNA) - 從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()); 
+0

有趣。我假設你的意思是'0x1040'?根據MSDN,這是「PROCESS_QUERY_LIMITED_INFORMATION」和「PROCESS_DUP_HANDLE」的聯合。如果你只是使用'0x1000'(刪除'PROCESS_DUP_HANDLE')會發生什麼?我猜測它正在切換到「PROCESS_QUERY_LIMITED_INFORMATION」,這有所作爲。 –

+0

P.S.這是基於http://msdn.microsoft.com/en-us/library/ms684880(v=VS.85).aspx。 –

回答

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)。

+0

謝謝!我更接近解決方案。進程現在不給我null。雖然GetModuleFileNameExA仍然失敗。 – David

+0

我修改了代碼。 – David

+0

有趣。GetLastError()返回訪問被拒絕。不是在OpenProcess之後,而是在GetModuleFileNameExA之後 – David

1

爲什麼所有的麻煩與進程id?從GetModuleFilename()的機制的文檔

引述:

HMODULE [在,可選]:

的句柄加載模塊,其路徑正被請求。如果 此參數爲NULL,則GetModuleFileName將檢索當前進程的可執行文件 的路徑。

如果您想要當前進程的模塊fileName,只需傳入NULL作爲進程ID。

如果你想要另一個進程的模塊文件名,在調用OpenProcess()之前你需要特定的訪問權限。更改訪問權限描述爲here,並且很難實現(它需要大量的步驟來查找特權名稱,獲取權限,調整權標特權等)。

+1

我已經通過將1040設置爲OpenProcess()的第一個參數找到了解決方案。感謝您的幫助,雖然:) – David