3
#include <iostream>
#include <fstream>
#define _WIN32_WINNT 0x501
#include <windows.h>

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

}

循环进行时每次按键的这段代码都应该在控制台上打印消息并创建一个文件,但是什么也没有发生。我错了什么?

4

4 回答 4

8

我将引用另一个主题

控制台窗口完全由 CSRSS 处理,这是一个系统进程。将钩子安装到进程中意味着将您的 DLL 注入其中。由于 CSRSS 非常重要(它对系统的运行至关重要,并且其中的代码作为 LocalSystem 运行,即本地超级管理员用户),因此不允许您向其中注入代码。所以你不能钩住它的任何窗户。

在您的简单控制台应用程序中没有发生真正的窗口消息,因此不必调用您的钩子,在您的情况下,您甚至没有注入钩子,而是仅使用线程模式钩子。根据 MSDN 文档,在即将处理消息时调用它:

与 SetWindowsHookEx 函数一起使用的应用程序定义或库定义的回调函数。每当应用程序调用 GetMessage 或 PeekMessage 函数并且有要处理的键盘消息(WM_KEYUP 或 WM_KEYDOWN)时,系统都会调用此函数。

现在让我向您展示如何开始在您的挂钩上接听电话:

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

MessageBox并且在关闭它之前开始输入 - 你将开始收到钩子调用。

于 2012-06-24T11:10:46.200 回答
1

阅读 SetWindowsHookEx 的文档。它是否正常工作,如果失败,它将返回 NULL,并且可以调用 GetLastError() 来获取错误代码以帮助诊断问题所在。

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

于 2012-06-24T10:08:53.383 回答
1

Sleep(1000)暂停当前​​线程的执行,直到超时间隔过去。这意味着您的程序在此睡眠期间实际上并未运行(即处理消息)。

您需要使用不同类型的命令,以保持消息循环运行。最简单的事情是等待用户输入

while(true)
   std::cin.get(); 
于 2012-06-24T10:49:37.527 回答
0

我创建了一个连接键盘的 dll,并在其中使用该DllMain函数检索HINSTANCE可用于SetWindowsHookEx.

除此之外,我还使用 0 作为 threadid,因此所有线程都被钩住了。

也许您也可以尝试类似的策略。

于 2012-06-24T12:10:06.983 回答