SetWindowsHook перестает работать через некоторое время

Я определил глобальный хук на WM_MOUSE, который отлично работает в течение некоторого времени. Он отправляет сообщение в определенное окно каждый раз, когда мышь двигается.

Через какое-то случайное время перехватывает перехват сообщений. Если я отменяю регистрацию и регистрирую хук, он снова работает. Я предполагаю, что какая-то конкретная вещь, происходящая в 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;
}

6 ответов

Решение

Вы проверили, установлен ли хук, когда он больше не вызывается (т.е. проверьте возвращаемое значение из BOOL UnhookWindowsHook)?

Возможно, установлен другой хук, который не сохраняет ваш хук, не вызывая CallNextHookEx().

Вы должны CloseHandle свою ручку крюка между прочим.

Единственное, о чем я могу думать, это может привести к сбою, если ваш хук дескриптор был уничтожен. Можете ли вы поймать исключение? Вы пытались прервать исключение, чтобы прервать его возникновение? Если вы не знаете, что происходит, вы пытались добавить блок __try/__finally вокруг вашего кода?

Попробуйте использовать WH_MOUSE_LL вместо.

Редактировать: о функции LowLevelMouseProc

Процедура подключения должна обработать сообщение за меньшее время, чем запись данных, указанная в значении LowLevelHooksTimeout в следующем разделе реестра:

HKEY_CURRENT_USER\Control Panel\Desktop

Значение в миллисекундах. Если процедура перехвата не возвращается в течение этого интервала, система передает сообщение следующему перехватчику.

Я предполагаю, что функция ловушки реализована в DLL? Может быть, что-то уменьшило количество ссылок на эту DLL, поэтому Windows выгружает его, что останавливает вашу функцию ловушки.

Я полагаю, что первое, что вы делаете внутри своей DLL - это вызываете LoadLibrary для себя, чтобы счетчик ссылок DLL, содержащей функцию ловушки, был увеличен на единицу. Убедитесь, что вы не вызвали FreeLibrary для проверки этой теории.

Являются ли важные данные для вашего хука в общем сегменте? Как минимум это будет HHOOK и HWND целевого окна, которое получает уведомления.

Опаздывая на вечеринку, но я также столкнулся с той же проблемой и решил ее, создав новый поток для выполнения своих задач и возврата из процедуры как можно скорее. Надеюсь, это кому-нибудь поможет.

Другие вопросы по тегам