5 Stimmen

SetWindowsHook funktioniert nach einiger Zeit nicht mehr

Ich habe einen globalen Haken für WM_MOUSE definiert, der seit einiger Zeit perfekt funktioniert. Es post eine Nachricht an ein bestimmtes Fenster jedes Mal die Maus bewegen.

Nach einer zufälligen Zeit hört der Haken auf, Nachrichten zu senden. Wenn ich die Registrierung aufhebe und den Hook wieder registriere, funktioniert er wieder. Ich vermute, dass irgendetwas Bestimmtes in Windows passiert, was den Hook zum Anhalten bringt, aber ich kann nicht herausfinden, was.

Irgendwelche Ideen?

bearbeiten : Ich habe einen Debugger an andere Prozesse angeschlossen, wenn der Hook nicht mehr aktiv ist, und ich habe festgestellt, dass die DLL nicht mehr geladen wird.

Was könnte dazu führen, dass eine Hook-DLL entladen wird?

Bearbeiten2 : Ich habe herausgefunden, dass ein Absturz der MouseHookProc dll in einem beliebigen Prozess die Hook dll von jedem Prozess, in dem sie geladen ist, entlädt. Ich kann keine Ursache für einen Absturz in meinem Code finden. Könnte es eine Race Condition oder etwas anderes sein? Hier ist der Code der Hook-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 Stimmen

Werden die Meldungen an andere Hooks in der Kette weitergegeben?

0 Stimmen

Mir ist aufgefallen, dass Sie zwar eine WH_MOUSE Haken verwenden Sie MSLLHOOKSTRUCT anstelle von MOUSEHOOKSTRUCT Struktur.

0 Stimmen

Eigentlich erklären Sie *mhs aber Sie benutzen es nicht.

3voto

RED SOFT ADAIR Punkte 11611

Haben Sie überprüft, ob der Hook noch installiert ist, wenn er nicht mehr aufgerufen wird (d.h. überprüfen Sie den Rückgabewert von BOOL UnhookWindowsHook)?

Möglicherweise ist ein anderer Hook installiert, der Ihren Hook nicht erhält und CallNextHookEx() nicht aufruft.

0 Stimmen

Wie Sie sehen können, führe ich in jedem Fall einen CallNextHookEx aus. UnhookWindowsHook ist höchstwahrscheinlich zurückkehren ok haben, weil ich einige Protokolle gibt es nichts protokolliert wurde.

0 Stimmen

Sie CallNextHookEx aufrufen, aber meine Vermutung war, dass irgendwo anders ein anderer Hook installiert ist, der CallNextHookEx nicht aufruft. Ich weiß nicht, ob es sich um ein großes Projekt handelt, bei dem Sie vielleicht in einem Team zusammenarbeiten. Wenn ja, scannen Sie den gesamten Code nach SetWindowsHookEx.

1voto

Nick Dandoulakis Punkte 41402

Versuchen Sie es mit WH_MOUSE_LL stattdessen.

Editar: über LowLevelMouseProc Funktion

Die Hook-Prozedur sollte die Verarbeitung einer Nachricht in weniger Zeit verarbeiten als die Daten Eintrag, der im Wert LowLevelHooksTimeout-Wert in der folgenden Registrierungsschlüssel angegeben ist:

HKEY_CURRENT_USER\Control Panel\Desktop

Der Wert wird in Millisekunden angegeben. Wenn die Hook-Prozedur nicht zurückkehrt während diesem Intervall nicht zurück, übergibt das System die Nachricht an den nächsten Hook weiter.

0 Stimmen

Ich habe es versucht, aber es brennt so oft, dass es alle Anwendungen verlangsamt und würde es irgendetwas lösen?

1 Stimmen

@Emmanuel Caradec, das sollten Sie nicht tun schwer innerhalb des Hook-Verfahrens arbeiten (es gibt eine zeitliche Begrenzung). Benachrichtigen Sie eine andere Routine, die die Aufgabe erledigen soll (vielleicht durch Senden einer Nachricht) und kehren Sie sofort zurück.

0 Stimmen

Eigentlich ist das Einzige, was ich tue, das Senden einer Nachricht an einen bereits bekannten Hwnd. Ich habe nicht viel mit wh_mouse_ll untersucht, da wm_mouse für mich funktioniert. Was ist das Problem mit wh_mouse?

1voto

Frerich Raabe Punkte 85859

Ich nehme an, dass die Hook-Funktion in einer DLL implementiert ist? Vielleicht hat etwas die Anzahl der Verweise auf diese DLL verringert, so dass Windows sie entlädt, was die Hook-Funktion stoppt.

Ich schlage vor, dass Sie als erstes in Ihrer DLL den Aufruf LoadLibrary auf sich selbst, so dass die Referenzanzahl der DLL, die die Hook-Funktion enthält, um eins erhöht wird. Achten Sie darauf, dass Sie nicht FreieBibliothek um diese Theorie zu testen.

1voto

Goz Punkte 59671

Sie sollten CloseHandle Ihre Haken Griff btw.

Die einzige Sache, die ich mir vorstellen kann, die einen Absturz verursachen würde, ist, wenn Ihr Hook-Handle zerstört wurde. Können Sie die Ausnahme abfangen? Haben Sie break on exception ausprobiert, um zu unterbrechen, wenn die Ausnahme auftritt, die gerade auftritt? Wenn Sie nicht wissen, welche Ausnahme auftritt, haben Sie versucht, einen __try/__finally-Block um Ihren Code herum einzufügen?

0 Stimmen

Ich werde heute einen __try/__finally-Block hinzufügen. Ich nehme an, dass es einen Absturz gibt, weil das genau das gleiche Verhalten verursachen würde. Ich habe versucht, einen Null-Zeiger zu dereferenzieren, und das führt zum Entladen jeder geladenen Hook-DLL. Windows fügt wahrscheinlich einen __try,__finally-Block um Hooks herum ein, um sie zu entladen, wenn sie sich schlecht verhalten.

0 Stimmen

Wann sollte ich einen geschlossenen Griff machen? Nach dem unhookwindowsex ?

0 Stimmen

Ganz genau. Für jeden Griff, den Sie "erstellen", sollten Sie ihn schließen. Ich bin mir ziemlich sicher, dass FindWindow nur ein bereits vorhandenes Handle zurückgibt, sodass es nicht geschlossen werden muss. Ich glaube, dass diese Verwirrung ist, warum COM die ganze addref/release Sache eingeführt :)

0voto

Bob Moore Punkte 6498

Befinden sich die wesentlichen Daten für Ihren Haken in einem gemeinsamen Segment? Dies wären zumindest der HHOOK und die HWND des Zielfensters, das Benachrichtigungsmeldungen empfängt.

0 Stimmen

Ja, der Haken funktioniert perfekt, über alle Windows und Thread für manchmal, dann hört es auf zu funktionieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X