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;
}

person Emmanuel Caradec    schedule 23.09.2009    source источник
comment
Вы распространяете сообщения на другие хуки в цепочке?   -  person rpg    schedule 05.10.2009
comment
Я заметил, что пока у вас есть WH_MOUSE хук, вы используете MSLLHOOKSTRUCT вместо структуры MOUSEHOOKSTRUCT.   -  person Nick Dandoulakis    schedule 09.10.2009
comment
Фактически вы объявляете *mhs, но не используете его.   -  person Nick Dandoulakis    schedule 09.10.2009
comment
Да, я тоже пробовал ловушки LL. Я не хотел слишком сильно редактировать код из-за страха удалить что-то значимое для ошибки. Конечно, mhs бесполезен, но я не понимаю, как это могло вызвать сбой или некорректное поведение.   -  person Emmanuel Caradec    schedule 09.10.2009
comment
Вы используете Windows 7? Я нашел эту тему: social.msdn .microsoft.com / Forums / en /, где обсуждается аналогичная проблема. У меня такая же проблема; если ЦП занят, время перехвата (по-видимому) истекает и больше никогда не вызывается.   -  person Thomas    schedule 11.03.2010
comment
Здравствуйте! Мы столкнулись с той же проблемой, но с клавиатурой LL. Вы нашли решение этой проблемы?   -  person sam    schedule 14.10.2010
comment
Мы обнаружили что-то в форме, что значения в общем сегменте, загруженном в другие процессы, не были правильными значениями. Это были ценности из прецедентного запуска. Похоже, это вызвано сбоем нашего исполняемого файла с последующей его немедленной перезагрузкой сторожевым таймером (DLL-файл перехвата должен быть выгружен, а затем перезагружен, но этого не происходит. Мы не уверены, почему, но скорость перезагрузки, похоже, является виновником .)   -  person Emmanuel Caradec    schedule 14.10.2010


Ответы (6)


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

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

person RED SOFT ADAIR    schedule 07.10.2009
comment
Как видите, я использую CallNextHookEx во всех случаях. UnhookWindowsHook, скорее всего, вернет нормально, потому что у меня есть журналы, в которых ничего не было зарегистрировано. - person Emmanuel Caradec; 08.10.2009
comment
Вы вызываете CallNextHookEx, но я предполагал, что где-то еще установлен другой перехватчик, который не вызывает CallNextHookEx. Не знаю, большой ли это проект, в котором вы, возможно, работаете в команде. Если да, просканируйте весь код для SetWindowsHookEx. - person RED SOFT ADAIR; 09.10.2009

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

Изменить: о функции LowLevelMouseProc < / а>

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

HKEY_CURRENT_USER\Control Panel\Desktop

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

person Nick Dandoulakis    schedule 23.09.2009
comment
Я пробовал, но он срабатывает так часто, что тормозит все приложения, и решит ли он что-нибудь? - person Emmanuel Caradec; 23.09.2009
comment
@Emmanuel Caradec, вы не должны выполнять тяжелую работу внутри процедуры подключения (есть ограничение по времени). Оповестите какой-нибудь другой распорядок о выполнении работы (например, отправив сообщение) и немедленно вернитесь. - person Nick Dandoulakis; 23.09.2009
comment
На самом деле единственное, что я делаю, это отправляю сообщение на уже знакомый hwnd. Я не особо разбирался с wh_mouse_ll, так как wm_mouse у меня работал. В чем проблема с wh_mouse? - person Emmanuel Caradec; 23.09.2009
comment
Очень долго пытался заблокировать wm_mouse, но dll не выгружалось. Это заставляет ПК работать медленно, но этого и следовало ожидать. - person Emmanuel Caradec; 06.10.2009

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

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

person Frerich Raabe    schedule 07.10.2009

Вам следует закрыть ручку крючка, кстати.

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

person Goz    schedule 08.10.2009
comment
Сегодня я добавлю блок __try / __ finally. Я предполагаю, что произошел сбой, потому что это привело бы к точно такому же поведению. Я попытался разыменовать нулевой указатель, и это привело к выгрузке каждой загруженной dll-ловушки. Windows, вероятно, добавит блокировку __try, __ finally вокруг хуков, чтобы выгрузить их, если они плохо себя ведут. - person Emmanuel Caradec; 09.10.2009
comment
Когда мне следует заниматься закрытием? После отцепления окна секс? - person Emmanuel Caradec; 09.10.2009
comment
Точно. Вы должны закрыть каждый созданный вами дескриптор. Я почти уверен, что FindWindow возвращает вам только уже существующий дескриптор, поэтому его не нужно закрывать. Я считаю, что из-за путаницы COM представил всю вещь addref / release :) - person Goz; 09.10.2009

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

person Bob Moore    schedule 23.09.2009
comment
Да, крючок работает отлично, иногда во всех окнах и потоках, затем он перестает работать. - person Emmanuel Caradec; 23.09.2009

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

person pgcan    schedule 30.03.2016