2016-06-17 150 views
0

我試圖觀察用全局Windows鉤子打開和關閉窗口。因此,我試圖將回調函數傳遞給包含我的鉤子程序的DLL。但是,鉤子程序本身永遠不會被調用。使用SetWindowsHookEx觀察打開的窗口

/** Handle to this DLL */ 
HINSTANCE dllModule = 0; 
/** Hook procedure */ 
HHOOK windowHook = 0; 
/** Callbacks are called when a new window is opened, or closed. */ 
HWND_CALLBACK windowOpenCallback = 0; 
HWND_CALLBACK windowCloseCallback = 0; 

WINDOWHOOK_API int WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID reserved) 
{ 
    if(reason == DLL_PROCESS_ATTACH) 
    { 
     dllModule = hInstance; 
     std::cout << "Process attached." << std::endl; 
    } 
    else if (reason == DLL_PROCESS_DETACH) 
    { 
     std::cout << "Process detached." << std::endl; 
    } 
    else if (reason == DLL_THREAD_ATTACH) 
    { 
    } 
    else if (reason == DLL_THREAD_DETACH) 
    { 
    } 
    return 1; 
} 

WINDOWHOOK_API bool setWindowHook(HWND_CALLBACK openCallback, HWND_CALLBACK closeCallback) 
{ 
    if(windowHook != 0 || windowOpenCallback != 0 || windowCloseCallback != 0) 
    { 
     return false; 
    } 
    windowOpenCallback = openCallback; 
    windowCloseCallback = closeCallback; 
    windowHook = SetWindowsHookEx(WH_SHELL, (HOOKPROC)hookCallback, dllModule, 0); 

    return windowHook != 0; 
} 

WINDOWHOOK_API bool releaseWindowHook() 
{ 
    bool result = windowHook != 0 && UnhookWindowsHookEx(windowHook) != 0; 

    windowHook = 0; 
    windowOpenCallback = 0; 
    windowCloseCallback = 0; 

    return result; 
} 

LRESULT CALLBACK hookCallback(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    std::cout << "Hook callback" << std::endl; 

    return CallNextHookEx(windowHook, nCode, wParam, lParam); 
} 

從我的主程序中,我加載庫並調用setWindowHook過程。然後,我簡單地啓動一個無限循環並等待被調用的鉤子,但儘管setWindowHook沒有失敗,但鉤子過程永遠不會被調用。我不明白爲什麼。

我試着設置一個WH_KEYBOARD掛鉤。有了這個,鉤子程序就被調用了按鍵,但只有當它們在我的程序的控制檯窗口內。

我正在編譯到64位機器上的32位。但是,它不應該至少適用於我所有的32位應用程序嗎?

在此先感謝。

+2

你的鉤子可能會被調用,但是它會在屬於它被注入的進程的線程上調用。它會嘗試在另一個進程的上下文中輸出到'std :: cout',並且對於大多數Windows進程來說,這將失敗,因爲它們沒有連接的控制檯。使用另一種方法監視您的掛鉤,而不涉及寫入控制檯。 –

+0

謝謝,那的確是問題所在。但是,現在我正面臨另一個問題。傳遞一個回調以便在窗口打開時被調用的想法實際上並不奏效。雖然我可以使所有加載了DLL的進程共享函數ptr,但進程無法調用它,因爲它們生活在不同的地址空間中。我怎麼讓他們與我的程序溝通?我可以發送窗口消息,但這些不能保證被處理,是嗎? –

+1

將消息發回主窗口(閱讀有關WM_COPYDATA)。共享內存將工作(通過適當的鎖定)。套接字可以工作,但你必須小心處理。 –

回答

0

謝謝,我得到它與DLL和SetWindowsHookEx,但SetWinEventHook解決方案的工作更好,你不需要一個DLL。 唯一的問題是,WINEVENTHOOK沒有LPVOID指針屬性,我們可以將類實例傳遞給它。所以如果你正在尋找一種面向對象的方法,並且正在努力,this codeproject link可能會有所幫助。

還要確保無論你設置鉤子的線程是否有消息循環,否則你將不會收到任何事件。

while (!stopped) 
{ 
    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) 
    { 
     // you don't have to do anything here 
    } 
}