2009-09-23 82 views
5

我在WM_MOUSE上定義了一個全局鉤子,它可以在一段時間內完美工作。每次鼠標移動時,它都會將消息發佈到特定的窗口。SetWindowsHook在一段時間後停止工作

經過一些隨機時間後,掛鉤停止發送消息。如果我取消註冊並註冊掛鉤,它會再次運行。我想在Windows中發生的一些具體事情會導致掛鉤停止,但我找不到。

任何想法?

編輯:當鉤子不再活躍時,我將調試器附加到其他進程,並且我觀察到dll不再被加載。

什麼可能導致掛鉤dll卸載?

編輯2:我發現在MouseHookProc中發生了崩潰,在任何進程中的dll都會從它加載的每個進程中卸載hook dll。我無法找到導致代碼崩潰的原因。可能是一些競爭條件或什麼?這裏是鉤子dll代碼:

#include "stdafx.h" 

// define a data segment 
#pragma data_seg(".SHARED") 
HWND hwnd=0; 
HHOOK hHook=0; 
#pragma data_seg() 

// tell the linker to share the segment 
#pragma comment(linker, "/section:.SHARED,RWS") 

#define WM_MOUSEHOOK   WM_USER+0x100 

HINSTANCE hInstance=0; 


// this allow to build a very small executable without any extra libraries 
// (probably not the problem, the bug still occurs without this) 
#ifndef _DEBUG 
void *__cdecl operator new(unsigned int bytes) 
{ 
    return HeapAlloc(GetProcessHeap(), 0, bytes); 
} 

void __cdecl operator delete(void *ptr) 
{ 
    if(ptr) HeapFree(GetProcessHeap(), 0, ptr); 
} 

extern "C" int __cdecl __purecall(void) 
{ 
    return 0; 
} 
#endif 

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
{  
    hInstance=hModule; 
    return TRUE; 
} 

LRESULT CALLBACK MouseHookProc(int nCode, WORD wParam, DWORD lParam) 
{ 
    if(nCode==HC_ACTION && (wParam==WM_MOUSEMOVE || wParam==WM_NCMOUSEMOVE)) 
    {    
     MSLLHOOKSTRUCT *mhs=(MSLLHOOKSTRUCT*)lParam;   
     PostMessage(hwnd, WM_MOUSEHOOK, wParam, 0); 
    } 
    return CallNextHookEx(hHook,nCode,wParam,lParam); 
} 

extern "C" __declspec(dllexport) HHOOK InitializeWindowsHook(char *title) 
{ 
    hwnd=FindWindow(0, title); 
    if(hwnd) 
     hHook=SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MouseHookProc, hInstance, 0); 
    return hHook; 
} 

extern "C" __declspec(dllexport) BOOL DeinitializeWindowsHook() 
{ 
    if(hHook) { 
     BOOL b=UnhookWindowsHookEx(hHook); 
     hHook=0; 
     return b; 
    } 
    return FALSE; 
} 
+0

你是否將消息傳播給鏈中的其他鉤子? – rpg 2009-10-05 12:19:12

+0

我注意到,雖然你有'WH_MOUSE'掛鉤,你可以使用'MSLLHOOKSTRUCT'而不是'MOUSEHOOKSTRUCT'結構。 – 2009-10-08 21:37:30

+0

其實你聲明'* mhs',但你不使用它。 – 2009-10-08 21:41:21

回答

2

你是否檢查過,如果掛鉤仍然安裝時,它不再被調用(即從BOOL UnhookWindowsHook檢查返回值)?

可能安裝了另一個鉤子,它不會保留您的鉤子,也不會調用CallNextHookEx()。

+0

正如你所看到的,我在每一種情況下都做了CallNextHookEx。 UnhookWindowsHook最有可能返回正常,因爲我有一些日誌沒有被記錄。 – 2009-10-08 16:49:54

+0

*您*調用CallNextHookEx,但我的假設是在別的地方安裝了不同的掛鉤,它不會調用CallNextHookEx。我不知道這是一個大型項目,你可能在一個團隊內進行協作。如果是這樣,請掃描SetWindowsHookEx的所有代碼。 – 2009-10-09 10:01:09

0

鉤子在共享段中的基本數據?至少這將是接收通知消息的目標窗口的HHOOK和HWND。

+0

是的,鉤子完美地工作,在所有的窗戶和線程中,有時會停止工作。 – 2009-09-23 11:20:50

1

請嘗試使用WH_MOUSE_LL代替。

編輯:LowLevelMouseProc Function

掛鉤過程應該在比在 的 LowLevelHooksTimeout值指定 條目的數據下面的註冊表項時間少處理 消息:

HKEY_CURRENT_USER\Control Panel\Desktop

該值以毫秒爲單位。如果 掛鉤程序在 這個間隔期間沒有返回,則系統將把 消息傳遞給下一個掛鉤。

+0

我嘗試過,但它經常發生火災,它減慢了所有的應用程序,它會解決什麼? – 2009-09-23 11:20:01

+1

@Emmanuel Caradec,你不應該在鉤子程序中做重*工作(有時間限制)。通知其他例行工作(可能通過發佈消息)並立即返回。 – 2009-09-23 11:25:37

+0

其實我唯一要做的就是給已經知道的hwnd發消息。自wm_mouse爲我工作以來,我沒有對wh_mouse_ll進行過很多調查。 wh_mouse有什麼問題? – 2009-09-23 11:50:33

1

我假設hook函數是在DLL中實現的?也許有些東西減少了該DLL的引用計數,所以Windows卸載它,這會停止你的鉤子函數。

我建議你在DLL裏面做的第一件事就是自己調用LoadLibrary,這樣包含鉤子函數的DLL的引用計數就加1。請務必不要撥打FreeLibrary來測試此理論。

1

你應該關閉你的鉤柄處理順便說一句。

我唯一能想到的就是會導致崩潰,如果你的鉤子手柄已經被銷燬。你能捕獲異常嗎?你是否嘗試過在發生異常時中斷異常?如果您不知道發生了什麼異常,您嘗試在代碼中添加__try/__ finally塊嗎?

+0

今天我會添加一個__try/__ finally塊。我想有一個崩潰,因爲這會導致完全相同的行爲。我試圖解引用空指針,這導致卸載每個加載的鉤子DLL。 Windows可能會添加一個__try,__ finally塊,如果它們表現不佳,可以將它們卸載。 – 2009-10-09 06:51:38

+0

我應該什麼時候做closehandle? unhookwindowsex之後?確切地說,是 – 2009-10-09 09:19:47

+0

。對於你「創建」的每個句柄,你應該關閉它。我很確定FindWindow只會返回一個預先存在的句柄,所以它不需要關閉。我相信混淆是爲什麼COM引入了整個addref/release的東西:) – Goz 2009-10-09 10:31:16

0

對晚會來說,但我也面臨同樣的問題,並通過創建一個新的線程來執行我的任務並從程序儘快返回來解決。希望這可以幫助某人。

相關問題