Как да прихващам натискания на клавиши към командния ред на Windows?

Работя върху специфичен за приложението инструмент за динамика на натискане на клавиш. Моето изискване е да получа данни за времето на потребител в подканата на Windows CMD. След няколко търсения открих 2 начина да направя това: 1) Използване на куки за Windows 2) Pyhook - модул за обвивка на Python

Струва ми се, че функционалността на моите приложения ще бъде доста подобна на тази на key-logger. Но не мога да разбера дали трябва да използвам глобални кукички или специфична кукичка за нишка за прихващане на натискания на клавиши към CMD подканата. И ако използвате глобална кука, възможно ли е да филтрирате натискания на клавиши въз основа на целевото приложение?


person secfreak    schedule 01.05.2012    source източник
comment
Защо вашето приложение просто не получава тези събития от натискане на клавиш? Защо трябва да го прихващате глобално за командния ред? Създали ли сте приложение за команден ред?   -  person Cody Gray    schedule 01.05.2012
comment
@CodyGray: Съжалявам, ако описанието ми е непълно. Написах конзолно приложение, което използва куката WH_KEYBOARD_LL. Мога да регистрирам натискания на клавиши и информация за тяхното време, но приложението регистрира на базата на цялата система. Сега се опитвам да огранича записването само от прозореца на CMD. Моля, уведомете ме дали има по-добър начин за изпълнение на задачата. Нов съм в печеленето на api и едва драскам повърхността. :)   -  person secfreak    schedule 01.05.2012
comment
Ако приложението ви работи в командния ред, защо не можете просто да го накарате да слуша събития от клавиатурата като нормално приложение? WH_KEYBOARD_LL кука е глобална кука на клавиатурата от ниско ниво — това означава, че ще получавате известия за всички събития на клавиатурата, които се случват в цялата система. Тъй като звучи сякаш това не е това, което искате, изобщо не искате глобална кука.   -  person Cody Gray    schedule 01.05.2012
comment
@CodyGray: Благодаря! Ще разгледам. Просто от любопитство: знаете ли за някакъв параметър или филтърна функция, която ще върне текущото приложение, от което се регистрират натисканията на клавиши, ако използвате глобална кука?   -  person secfreak    schedule 01.05.2012
comment
Не, такова нещо не е възможно. Целият смисъл на глобалната кука, особено тази на ниско ниво, е, че вашата кука процедура получава известие за събитието, преди да бъде предадено на което и да е приложение. Ето защо можете да консумирате/анулирате събитието и да предотвратите обработката му от приложение. Инсталирането на кука основно вмъква вашата кука процедура в работата нагоре на всичко останало. (Но както казах, честно казано не разбирам защо се нуждаете от кука. Изглежда, че можете просто да обработите нормално въвеждане от клавиатурата, насочено към вашето конзолно приложение.)   -  person Cody Gray    schedule 01.05.2012
comment
@CodeGray: Не искам събитията от натискане на клавиши да се насочват към конзолното ми приложение. Искам моето конзолно приложение да слуша за събития натискане на клавиши в подканата на Windows CMD или подкана на powershell.   -  person secfreak    schedule 01.05.2012


Отговори (1)


Този добър код по-долу е приложение за бързи клавиши, което се намира във фонов режим и слуша комбинацията от клавиши 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;

}
person Software_Designer    schedule 01.05.2012