KeyboardHook Programmfokus
-
hallo zusammen
Ich hab mich seit ner Weile mit WinApi beschäftigt und mir zum Ziel gesetzt n funktionierenden KeyboardHook zu programmieren. Hab sämmtliche Threads die dieses Thema behandeln schon durchgeackert, sowie das DLL-TUT im bereich WinAPI FAQ/Archiv. Mit all dem gesammelten Wissen und den gesammelten Informationen hab ich folgenden Code zusammengestellt.
Problem: Die InstallHook / DeinstallHook Funktionen funktionieren und können sauber aufrufen werden. Doch wenn ich den Hook gesetzt hab und dann n paar Tasten drücken zum Testen, führt das Prog die KeyboardProc-CALLBACK Funktion nicht aus (Kein "printf ("keystroke\n", siehe Code);".
Compiler: LabWindows/CVI 8.5 Compiler
Schauts euch ma an:
//Dll:************************************************************************* //maindll.h******************************************************************** //-- include-Anweisungen ------------------------------------------------------ #include <windows.h> //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //This function installs the Keyboard hook. __declspec(dllexport) void InstallHook(void); //This function removes the previously installed hook. __declspec(dllexport) void UninstallHook(void); //This function is called when the keyboard is operated. LRESULT CALLBACK KeyboardProc (int ncode,WPARAM wparam,LPARAM lparam); //----------------------------------------------------------------------------- //maindll.c******************************************************************** //-- include-Anweisungen ------------------------------------------------------ #include <windows.h> #include <ansi_c.h> #include "dllmain.h" //----------------------------------------------------------------------------- //Shared-Data-Segment #pragma data_seg("Shared") HHOOK hook = NULL; // Handle Hook (als "shared") #pragma data_seg() #pragma comment (linker, "/section:Shared,RWS") //linker directive HINSTANCE hinstance = NULL; //Handle Dll //Dll-Hauptfunktion //----------------------------------------------------------------------------- BOOL APIENTRY DllMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { hinstance = hModule; return TRUE; } //----------------------------------------------------------------------------- //Installationsfunktion //----------------------------------------------------------------------------- __declspec(dllexport) void InstallHook (void) { hook = NULL; hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hinstance, 0); if(hook != NULL) printf("Install hook sucessful\n"); //Installation überprüfung } //----------------------------------------------------------------------------- //Deinstallationsfunktion //----------------------------------------------------------------------------- __declspec(dllexport) void UninstallHook (void) { if(hook != NULL) { UnhookWindowsHookEx(hook); hook = NULL; printf("Uninstall hook sucessful\n"); //Deinstallation überprüfung } } //----------------------------------------------------------------------------- //Keystroke Callback //----------------------------------------------------------------------------- LRESULT CALLBACK KeyboardProc (int ncode, WPARAM wparam, LPARAM lparam) { if(ncode>=0) { if((lparam & 0x80000000) == 0x00000000) //Keystroke oder Keyrelease? { printf ("keystroke\n"); //Callbackaufruf überprüfen } } return ( CallNextHookEx(hook,ncode,wparam,lparam) ); //Nächster Hook in der Hook-Kette aufrufen } //Hauptprogramm:*************************************************************** //kl.h************************************************************************* void SWSetUp (void); void SWCleanUp (void); //kl.c************************************************************************* //-- include-Anweisungen ------------------------------------------------------ #include <windows.h> #include <ansi_c.h> #include "kl.h" //----------------------------------------------------------------------------- //-- Typendeklarationen ------------------------------------------------------- typedef void (*InstallHookType)(void); typedef void (*UninstallHookType)(void); //----------------------------------------------------------------------------- HINSTANCE DllHandle; BOOL fFreeResult; //Hauptfunktion //----------------------------------------------------------------------------- void main (void) { SWSetUp(); //maincode getchar(); //zum drücken von paar tasten benötigt SWCleanUp(); return; } //----------------------------------------------------------------------------- //Software initalisieren //----------------------------------------------------------------------------- void SWSetUp (void) { InstallHookType InstallFunc; //dll laden DllHandle = LoadLibrary("klDll.dll"); //hook installieren if (DllHandle) { InstallFunc = (InstallHookType) GetProcAddress (DllHandle, "InstallHook");// Die Einsprungadresse abfragen if (InstallFunc) { (*InstallFunc) (); } } return; } //----------------------------------------------------------------------------- //Software deinitalisieren //----------------------------------------------------------------------------- void SWCleanUp (void) { UninstallHookType UninstallFunc; //hook deinstallieren if (DllHandle) { UninstallFunc = (UninstallHookType) GetProcAddress (DllHandle, "UninstallHook");// Die Einsprungadresse abfragen if (UninstallFunc) { (*UninstallFunc) (); } } //dll entladen fFreeResult = FreeLibrary(DllHandle); return; } //-----------------------------------------------------------------------------Bin um jede Hilfe dankbar.
-
soweit ich das sehe, hast du keinen Aufruf von GetMessage bzw. Peek Message in deinem Hauptprogramm. irgendwo in der msdn steht aber *zu erinnern versuch* das du eine nachrichtenschleife brauchst.
hoffe das ist richtig ist, ist nämlich schon ne weile her bei mir.
alle angaben sind wie immer ohne gewähr
-
Ich dachte ich brauch im Hauptprogramm nur ne GetMessage() wenn ich auch die Nachricht ans Hauptprogramm senden will, nicht? Wenn ich doch nur die KeyboardProc aufrufen lassen will ohne gross die Daten zu verarbeiten sollte das doch reichen, also das mit der printf-Überprüfung. Korrigiert mich wenn ich mich irre...
(p.s. bin noch ziemlich unerfahren was WinAPI angeht, von dem her nich böse werden wenn ich hier komische Sachen von mir gebe :p )
-
versuch mal
//Anfang davor MSG msg; while(true)//durch abruchbedingung ersetzen { PeekMessage(&msg,0,0,0,PM_NOREMOVE); Sleep(10); } //rest...
-
ok, die Callback-Funktion in der Dll wird nun aufgerufen, danke
nochwas:
wenn ich doch was mit PostMessage() schicken will muss ich da n Fensterhandle (hWnd) angeben, zu dem die Nachricht gehen soll oder? Und wenn ich nun kein Fenster habe, sondern einfach das Programm das die Daten verarbeiten soll wie soll ich das anstellen das die Funktion (KeyboardProc) in der Dll die Daten an mein Hauptprogramm schickt, kann man da auch irgend n ProgrammHandle mitgeben oder wie funktioniert das?
-
Da brauchst du PostThreadMessage mit der "Process Id" deines Haupt Threads (kann man z.B. mit GetCurrentThreadId ermitteln und der Dll-Funktion als Parameter mitgeben

btw: "böse" werd ich nur bei kommentaren wie "booh ej is dat kage"(rechtschreibung übernommen)

-
Fencer schrieb:
Da brauchst du PostThreadMessage mit der "Process Id" deines Haupt Threads
Das is die von der Hauptfunktion oder? (hInstance bei mir jetzt)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { //code }
-
Mach doch einfach einen neuen Parameter für die InstallHook function.

-
Danke Fencer für die bisherige Hilfe
Funktioniert soweit nun alles, wenn ich nun die Daten an mein Hauptprogramm übergebe während das Hauptprogramm aktiv ist (Taskleiste -> ausgewählt), bearbeitet es die Daten. Wenn ich aber nun irgendwo anders ne Taste drücke, solange das Hauptprogramm nicht aktiv ist wird nichts bearbeitet, was ja auch logisch ist!
Hat einer eine Idee wie ich mein Hauptprogramm dazu bringe auch zu arbeiten während ich n anderes Programm aktiv habe, ohne die Verarbeitung in der Dll zu machen? Ist das überhaupt möglich?
-
Gern geschehen

vllt. wenn du beim SetWindowsHookEx mal WH_KEYBOARD_LL(siehe msdn) versuchst. ist aber nur ne vermutung.
-
muss ins shared datensegment, zeig dein code.
-
//Shared-Data-Segment #pragma data_seg("Shared") HHOOK hook = NULL; // Handle Hook (als "shared") #pragma data_seg() #pragma comment (linker, "/section:Shared,RWS") //linker directivewas muss sonst denn noch da rein?
-
die process id natürlich, ist doch sonnenklar wie schwarzbrot.
-
Ok is mir nun klar warum die da rein muss.
Ich übergebe der Dll die ThreadID meines Hauptprogrammes mit der InstallHook-Funktion und speichere sie in myAPP.
So sieht mein shared nun aus:
//Dll.c //Shared data segment #pragma data_seg("Shared") HHOOK hook = NULL; // HookHandle (als "shared" Deklariert) DWORD myApp; //ThreadId des Programmes an das die Daten gesendet werden sollen #pragma data_seg()Die Callback-Funktion wird immer ordnungsgemäss aufgerufen:
//Dll.c LRESULT CALLBACK KeyboardProc (int ncode, WPARAM wParam, LPARAM lParam) { if(ncode>=0) { if((lParam & 0xE0000000) == 0x00000000) //Key filter { // Beep(1700,100); PostThreadMessage(myApp, WM_USER+100, wParam, lParam); //Daten an Hauptprogramm senden } } return ( CallNextHookEx(hook,ncode,wParam,lParam) ); //Nächster Hook in der Hook-Kette aufrufen }So sieht meine Hauptschleife im Hauptprogramm nun aus die die Daten erhalten soll:
//hauptprogramm.c while (msg.wParam != 27) //Austrittsbedinung erfüllt bei drücken von Esc { GetMessage(&msg, NULL, 0, 0); if(msg.message == WM_USER+100) { KeyStrokeProcessing(msg.wParam, msg.lParam); //Daten verarbeiten } DispatchMessage(&msg); //MSG verteilen }Wenn ich mein Hauptprogramm aktiv habe kriegt es die Daten, sobald ich aber n anderes Programm aktiviere erhält es die Daten nicht mehr, die Callback-Funktion in der Dll wird aber aufgerufen, an was kann das liegen?
mfg elDorado
-
Habe ungefähr das selbe Problem und bis jetzt noch keine Lösung gefunden, bleib aber dran.
-
hab bei anderen projekten gesehen das die vor der PostMessage in der dll zuerst das handle des fensters mithilfe von FindWindow suchen und dann direkt dahin schicken. veruch doch mal n fenster zu erstellen, es dann aber nicht anzuzeigen, da ich mal annehme das dein programm ja eigentlich kein gui haben soll, mehr fällt mir dazu au ned ein.
-
get last error

-
was soll ich nu mit der Antwort anfangen?