SetWindowsHookEx met WH_KEYBOARD werkt niet voor mij, wat heb ik fout?

#include 
#include 
#define _WIN32_WINNT 0x501
#include 

using namespace std;

HHOOK hKeyboardHook = 0;
LRESULT CALLBACK KeyboardCallback(int code,WPARAM wParam,LPARAM lParam) {  
  cout << "a key was pressed" << endl;
  ofstream myfile;
  myfile.open ("hookcheck.txt", ios::ate | ios::app);
  myfile << "a key was pressed\n";
  myfile.close();
  return CallNextHookEx(hKeyboardHook,code,wParam,lParam);
}

int main() {

  HWND consoleWindow = GetConsoleWindow();
  HINSTANCE hInstCons = (HINSTANCE)GetWindowLong( consoleWindow, GWL_HINSTANCE );
  hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyboardCallback, (HINSTANCE)consoleWindow, GetCurrentThreadId());

  MessageBox(NULL, "It is keyboard time!", "Let's Go", MB_OK);

}

Deze code bij elke toetsindruk terwijl de lus loopt, moet een bericht op de console afdrukken en een bestand maken, maar er gebeurt niets. Wat heb ik fout?

3
@MatteoItalia: Dat is interessant, kun je me een link naar handleiding geven, ik ben niet helemaal zeker over welke api je aan het praten bent en ik was op zoek naar deze vele dagen.
toegevoegd de auteur rsk82, de bron
SetWindowsHookEx haakt Windows-berichten. Een console-app gebruikt geen berichten. U moet een native Windows-app schrijven die een berichtenlus pompt.
toegevoegd de auteur Hans Passant, de bron
Trouwens, Windows-console biedt API's met een laag niveau, gebruik deze in plaats van haken te gebruiken.
toegevoegd de auteur Matteo Italia, de bron
Start vanuit hier .
toegevoegd de auteur Matteo Italia, de bron
Deze pagina moet relevant zijn voor uw doel .
toegevoegd de auteur Matteo Italia, de bron

4 antwoord

Ik citeer van een ander onderwerp :

Consolevensters worden volledig behandeld door CSRSS, een systeem   werkwijze. Het installeren van een haak in een proces betekent het injecteren van uw DLL   erin. Omdat CSRSS zo belangrijk is (het is van vitaal belang voor het uitvoeren van de   systeem en code binnen wordt uitgevoerd als LocalSystem, dat het lokale is   super-admin gebruiker), je mag er geen code in invoeren. Dus jij   kan geen van zijn vensters inhaken.

Er zijn geen echte berichten in het venster die plaatsvinden in uw eenvoudige consoletoepassing, dus uw haak hoeft niet te worden gebeld en in uw geval injecteert u niet eens uw haak, maar gebruikt u alleen de hook hook. Per MSDN-documentatie wordt dit genoemd wanneer berichten worden verwerkt:

Een toepassingsgerichte of bibliotheek-gedefinieerde callback-functie gebruikt met   de SetWindowsHookEx-functie. Het systeem roept deze functie altijd aan   een toepassing roept de functie GetMessage of PeekMessage en daar   is een toetsenbordbericht (WM_KEYUP of WM_KEYDOWN) dat moet worden verwerkt.

Laat me je nu laten zien wat je kunt doen om oproepen aan je haak te ontvangen:

MessageBox(NULL, _T("It is keyboard time!"), _T("Let's Go"), MB_OK);

//for(int i=0; i<=10; i++) {
//  cout << i << endl;
//  Sleep(1000);
//}

Voer MessageBox uit en voordat je het sluit, begin je met typen - je krijgt haakoproepen.

8
toegevoegd
Als ik begrijp welke tekst je aanhaalt, werkt SetWindowsHookEx niet met console-apps, toch? Ik heb mijn code in kwestie bijgewerkt en deze werkt nog steeds niet.
toegevoegd de auteur rsk82, de bron
Sorry, ik doe niet wat ik verkeerd doe, maar er worden geen evenementen voor mij getoond. (Ik gebruik gcc 4.7.0 mingw)
toegevoegd de auteur rsk82, de bron
Ja, inderdaad, ik ben dit vergeten, nu werkt het. Dank je.
toegevoegd de auteur rsk82, de bron
Nee, ik heb geprobeerd het op beide manieren te doen, dat wil zeggen met het venster in de voorgrond- en achtergrondmodus. Wanneer het berichtenvak op voorgrond staat, klinkt er bij elke druk op de knop een god, maar er wordt niets op de console weergegeven.
toegevoegd de auteur rsk82, de bron
Uw binary werkt ook niet zoals verwacht. Dat wil zeggen dat het zonder enige fout werkt, maar ook niet reageert op toetsaanslagen, precies hetzelfde als door mij gecompileerde code. Misschien is dit een Windows-probleem, ik gebruik XP SP3.
toegevoegd de auteur rsk82, de bron
Werkt voor mij. Zorg ervoor dat uw berichtvak op de voorgrond staat, maar druk niet op de knop om het te sluiten. Typ daar iets. Dit genereert toetsenbordberichten in de thread waar u de haak hebt geïnstalleerd. Je haak wordt gebeld.
toegevoegd de auteur Roman R., de bron
Dit komt omdat je niet controleert volgens de suggestie van Scott Langham. U hebt de haak niet geïnstalleerd in XP, omdat in XP GetWindowLong het niet-NULL-resultaat wordt geretourneerd en u daar NULL moet hebben (zie bijgewerkte code).
toegevoegd de auteur Roman R., de bron
Ik weet niet zeker of dit nuttig zal zijn, maar dit is mijn bron en binaire alax.info/trac/public/browser/trunk/Utilities/… U kunt ook het hulpprogramma Spy ++ gebruiken om te controleren welke berichten in uw proces voorkomen.
toegevoegd de auteur Roman R., de bron
Hoogstwaarschijnlijk typt u zonder berichtvenster op de voorgrond en wordt de toetsenbordinvoer niet naar het venster en de thread van interesse geleid.
toegevoegd de auteur Roman R., de bron
Ik ben bezig met C-programmering, ik heb ShowWindow (hwnd, FALSE) gebruikt voor mijn consolevenster en SetWindowsHookEx() werkt niet wanneer ik dat doe. Komt het omdat mijn programma een achtergrondproces wordt?
toegevoegd de auteur turmuka, de bron
Ik zet ShowWindow() -functie vlak voor mijn GetMessage() -functie-loop zodat het programma kan doorgaan
toegevoegd de auteur turmuka, de bron

Lees de documentatie voor SetWindowsHookEx. Werkt het, dan wordt NULL geretourneerd als het mislukt en kan GetLastError() worden aangeroepen om een ​​foutcode op te halen om te helpen vaststellen wat er mis is.

http://msdn.microsoft. com/en-us/library/windows/desktop/ms644990 (v = vs.85) .aspx

1
toegevoegd
toegevoegd de auteur Scott Langham, de bron
GetLastError() retourneert 0 . - Waar kan ik vinden wat het betekent?
toegevoegd de auteur rsk82, de bron
En dat is waar. Er is iets vreemds aan de hand, code compileert zonder fouten en er is nergens een foutmelding in de code, alleen terugbellen initialiseert niet.
toegevoegd de auteur rsk82, de bron

Sleep(1000) suspends the execution of the current thread until the time-out interval elapses. It means that your program is not actually running (ie. processing messages) during this sleep.

U moet een ander soort commando gebruiken, dat ervoor zorgt dat de berichtenlus blijft lopen. Het eenvoudigste is om te wachten op gebruikersinvoer

while(true)
   std::cin.get(); 
1
toegevoegd

Ik heb een dll gemaakt die het toetsenbord heeft aangesloten en daar gebruik ik de DllMain functie om een ​​ HINSTANCE op te halen die kan worden gebruikt in SetWindowsHookEx .

Daarnaast heb ik ook 0 als threadid gebruikt, dus alle threads raken verslaafd.

Misschien kun je ook een soortgelijke tactiek proberen.

0
toegevoegd