2009-09-23 5 views
5

잠시 동안 완벽하게 작동하는 WM_MOUSE에 전역 훅을 정의했습니다. 마우스를 움직일 때마다 특정 창에 메시지를 게시합니다.잠시 후 SetWindowsHook이 작동을 멈 춥니 다.

임의의 시간이 지나면 후크가 메시지를 보내지 않습니다. 등록을 취소하고 연결 고리를 등록하면 다시 작동합니다. 나는 Windows에서 일어나는 어떤 특정한 일이 후크를 멈추게 할 것이라고 생각하지만, 나는 무엇을 찾을 수 없다.

아이디어가 있으십니까?

편집 : 후크가 더 이상 활성화되어 있지 않을 때 디버거를 다른 프로세스에 연결하고 dll이 더 이상로드되지 않는 것을 관찰했습니다.

후크 dll을 언로드시킬 수있는 원인은 무엇입니까?

Edit2가 : 나는 MouseHookProc에서 충돌이 모든 프로세스에 DLL이이에 장전 모든 프로세스에서 후크 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

+0

'WH_MOUSE' 훅이있는 동안'MOUSEHOOKSTRUCT' 구조체 대신에'MSLLHOOKSTRUCT'를 사용하는 것으로 나타났습니다. –

+0

실제로'* mhs '를 선언했지만 사용하지는 않습니다. –

답변

2

훅이 더 이상 호출되지 않으면 (즉, BOOL UnhookWindowsHook의 반환 값을 확인하는 경우) 훅이 아직 설치되어 있는지 확인 했습니까?

아마도 CallNextHookEx()를 호출하지 않고 후크를 보존하지 않는 다른 후크가 설치되었을 수 있습니다.

+0

알다시피 나는 모든 경우에 CallNextHookEx를 수행합니다. 로그가 없기 때문에 UnhookWindowsHook이 반환 확률이 높습니다. –

+0

* You * CallNextHookEx를 호출하지만, 내 가정은 CallNextHookEx를 호출하지 않는 다른 훅이 설치되어있는 것입니다. 이 프로젝트가 대규모 프로젝트인지는 잘 모릅니다. 팀에서 협업 할 수 있습니다. 그렇다면 SetWindowsHookEx에 대한 모든 코드를 검사하십시오. –

0

공유 세그먼트에서 사용자의 후크에 필수적인 데이터입니까? 최소한 알림 메시지를 수신하는 대상 윈도우의 HHOOK 및 HWND가됩니다.

+0

예 모든 창문과 실에 걸쳐 때로는 완벽하게 작동하는 후크가 작동하지 않습니다. –

1

대신 WH_MOUSE_LL을 사용해보세요.

편집 :에 대한 LowLevelMouseProc Function

레지스트리 키 다음 항목이 에서 LowLevelHooksTimeout 값에 지정된 데이터보다 적은 시간에 메시지를 처리해야하는 후크 프로 시저 :

HKEY_CURRENT_USER\Control Panel\Desktop

값은 밀리 초입니다. 이 간격 동안 후크 프로 시저가 동안 반환되지 않으면 시스템은 메시지를 다음 후크로 전달합니다.

+0

나는 그것을 시험해 보았지만 너무 자주 발사되어 모든 응용 프로그램의 속도를 늦추고 아무 것도 해결하지 않겠습니까? –

+1

@Emmanuel Caradec, 후크 절차 (무한한 *) 작업을해서는 안됩니다 (시간 제한 있음). 다른 루틴에게 (아마도 메시지 게시를 통해) 작업을 알리고 즉시 반환하십시오. –

+0

사실 내가하는 일은 이미 알고있는 hwnd에게 메시지를 보내는 것뿐입니다. wm_mouse가 나를 위해 일한 이후로 wh_mouse_ll을 많이 조사하지는 않았습니다. wh_mouse의 문제점은 무엇입니까? –

1

후크 기능이 DLL에 구현되어 있다고 가정합니까? 어쩌면 무언가가 해당 DLL의 참조 횟수를 줄이면 Windows가이 DLL을 언로드하므로 훅 기능이 중지됩니다.

DLL에서 가장 먼저 할 일은 LoadLibrary을 호출하여 후크 기능이 포함 된 DLL의 참조 횟수를 1만큼 증가시키는 것입니다. 이 이론을 테스트하려면 FreeLibrary으로 전화하지 마십시오.

1

후크 핸들 btw를 CloseHandle해야합니다.

내가 생각할 수있는 유일한 문제는 충돌이 발생하는 원인은 후크 핸들이 파괴 된 경우입니다.예외를 잡을 수 있습니까? 예외가 발생했을 때 휴식을 취하려고 했습니까? 어떤 예외가 발생하는지 모르는 경우 코드 주위에 __try/__ finally 블록을 추가하려 했습니까?

+0

오늘 __try/__ finally 블록을 추가하겠습니다. 그것이 똑같은 행동을 일으킬 것이기 때문에 충돌이 있다고 생각합니다. dereferencing null 포인터를 시도하고이 모든로드 된 후크 dll 언로드 원인이. Windows는 아마도 __try를 추가하고, __ finally 블록이 후크 주변을 차단하여 잘못 작동하면 언로드합니다. –

+0

클로즈드 핸들은 언제해야합니까? 후크 윈드 서 섹스 후? –

+0

정확히. 당신이 "창조"하는 모든 손잡이를 위해 그것을 닫아야합니다. FindWindow는 기존 핸들을 반환하기 때문에 닫을 필요가 없습니다. COM이 전체 addref/release를 도입 한 이유는 혼란이라고 생각합니다. :) – Goz

0

파티에 늦었지만 동일한 문제가 발생하여 새로운 작업을 실행하고 절차에서 다시 돌아 오는 스레드를 만들어 해결했습니다. 희망이 사람을 도움이됩니다.

관련 문제