【问题标题】:How to intercept keystrokes to windows command prompt?如何拦截对 Windows 命令提示符的击键?
【发布时间】:2012-05-10 18:41:37
【问题描述】:

我正在开发一个特定于应用程序的击键动态工具。我的要求是在 Windows CMD 提示符 中获取用户的击键计时数据。经过几次搜索,我发现了两种方法: 1)使用windows钩子 2) Pyhook - python 包装模块

在我看来,我的应用程序功能将与键盘记录器的功能非常相似。但是我无法弄清楚是否应该使用全局挂钩或线程特定挂钩来拦截对 CMD 提示的击键。如果使用全局挂钩,是否可以根据目标应用程序过滤击键?

【问题讨论】:

  • 为什么您的应用程序不接收这些击键事件?为什么需要在命令提示符下全局拦截?您是否创建了命令行应用程序?
  • @CodyGray:如果我的描述不完整,我很抱歉。我编写了一个使用 WH_KEYBOARD_LL 挂钩的控制台应用程序。我能够记录击键及其时间信息,但该应用程序在系统范围内记录。现在,我试图限制仅从 CMD 窗口进行日志记录。如果我有更好的方法来完成这项任务,请告诉我。我是赢得 api 的新手,我几乎没有触及表面。 :)
  • 如果您的应用程序在命令提示符下运行,为什么不能让它像普通应用程序一样监听键盘事件? WH_KEYBOARD_LL 钩子是一个全局的、低级的键盘钩子——这意味着您将收到系统范围内发生的所有 键盘事件的通知。因为这听起来不是你想要的,所以你根本不想要一个全局钩子。
  • @CodyGray:谢谢!我会调查的。只是出于好奇:如果使用全局挂钩,您是否知道任何参数或过滤器函数将返回正在记录击键的当前应用程序?
  • 不,这样的事情是不可能的。全局挂钩(尤其是低级别挂钩)的全部意义在于,您的挂钩过程会在事件通知被传递给任何应用程序之前收到通知。这就是为什么您可以使用/取消事件并防止它被应用程序处理的原因。安装挂钩基本上会将您的挂钩程序插入到其他所有工作的上游中。 (但就像我说的,我真的不明白你为什么需要一个钩子。看起来你可以只处理针对你的控制台应用程序的普通键盘输入。)

标签: c++ winapi keyboard keylogger keystrokes


【解决方案1】:

下面这个好代码是一个 Hotkey 应用程序,它位于后台侦听 CTRL-y 组合键,您可以修改或向应用程序添加更多组合键。隐藏时使用CTRL-q退出应用。

如果您希望完全隐藏控制台窗口,请在 main() 中取消注释此行://ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false)。享受吧。

if (CTRL_key !=0 && key == 'y' )
{
   MessageBox(NULL, "CTRL-y was pressed\nLaunch your app here", "H O T K E Y", MB_OK); 
   CTRL_key=0;
}

完整代码清单:

#define _WIN32_WINNT 0x0400
#pragma comment( lib, "user32.lib" )

#include <windows.h>
#include <stdio.h>

HHOOK hKeyboardHook;

__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam)
{
    DWORD SHIFT_key=0;
    DWORD CTRL_key=0;
    DWORD ALT_key=0;

    if  ((nCode == HC_ACTION) &&   ((wParam == WM_SYSKEYDOWN) ||  (wParam == WM_KEYDOWN)))      
    {
        KBDLLHOOKSTRUCT hooked_key =    *((KBDLLHOOKSTRUCT*)lParam);
        DWORD dwMsg = 1;
        dwMsg += hooked_key.scanCode << 16;
        dwMsg += hooked_key.flags << 24;
        char lpszKeyName[1024] = {0};
        lpszKeyName[0] = '[';

        int i = GetKeyNameText(dwMsg,   (lpszKeyName+1),0xFF) + 1;
        lpszKeyName[i] = ']';

        int key = hooked_key.vkCode;

        SHIFT_key = GetAsyncKeyState(VK_SHIFT);
        CTRL_key = GetAsyncKeyState(VK_CONTROL);
        ALT_key = GetAsyncKeyState(VK_MENU);

        if (key >= 'A' && key <= 'Z')   
        {

            if  (GetAsyncKeyState(VK_SHIFT)>= 0) key +=32;

            if (CTRL_key !=0 && key == 'y' )
            {
               MessageBox(NULL, "CTRL-y was pressed\nLaunch your app here", "H O T K E Y", MB_OK); 
               CTRL_key=0;
            }

            if (CTRL_key !=0 && key == 'q' )
            {
                MessageBox(NULL, "Shutting down", "H O T K E Y", MB_OK); 
               PostQuitMessage(0);
            }




            printf("key = %c\n", key);

            SHIFT_key = 0;
            CTRL_key = 0;
            ALT_key = 0;

        }

        printf("lpszKeyName = %s\n",  lpszKeyName );
    }
    return CallNextHookEx(hKeyboardHook,    nCode,wParam,lParam);
}

void MessageLoop()
{
    MSG message;
    while (GetMessage(&message,NULL,0,0)) 
    {
        TranslateMessage( &message );
        DispatchMessage( &message );
    }
}

DWORD WINAPI my_HotKey(LPVOID lpParm)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance) hInstance = LoadLibrary((LPCSTR) lpParm); 
    if (!hInstance) return 1;

    hKeyboardHook = SetWindowsHookEx (  WH_KEYBOARD_LL, (HOOKPROC) KeyboardEvent,   hInstance,  NULL    );
    MessageLoop();
    UnhookWindowsHookEx(hKeyboardHook);
    return 0;
}

int main(int argc, char** argv)
{
    HANDLE hThread;
    DWORD dwThread;

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)   my_HotKey, (LPVOID) argv[0], NULL, &dwThread);

    //ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);

    if (hThread) return WaitForSingleObject(hThread,INFINITE);
    else return 1;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多