Глобальная клавиатура хук не работает - PullRequest
2 голосов
/ 24 января 2010

Я создал глобальный хук клавиатуры.

Крюк создан в DLL.

#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
static HHOOK hkb=NULL;
static CMyFile *pLF;
#pragma data_seg()

HINSTANCE hins = NULL;

extern "C"
LRESULT  __declspec(dllexport) __stdcall  CALLBACK KeyBoardHookProc(
    int nCode, 
    WPARAM wParam, 
    LPARAM lParam)
{

if (nCode < 0) {
        return CallNextHookEx(0, nCode, wParam, lParam);
    }

    return CallNextHookEx(hkb, nCode, wParam, lParam);
}

extern "C"
LRESULT __declspec(dllexport) __stdcall CALLBACK Install()
{
    pLF = new CMyFile(L"c:\\1.txt");
    hkb = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyBoardHookProc,hins,0);
    return 0;

}

extern "C"
BOOL __declspec(dllexport) __stdcall CALLBACK UnInstall()
{
    return UnhookWindowsHookEx(hkb);
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{

    switch(ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH :
        hins = (HINSTANCE) hModule;
        break;

    case DLL_THREAD_ATTACH :
        break;

    case DLL_THREAD_DETACH :
        break;

    case DLL_PROCESS_DETACH :
        break;
    }
    return TRUE;
}

Я создал один EXe, который загружает эту библиотеку DLL и вызывает функцию установки библиотеки DLL.

 HMODULE hMod = LoadLibrary(L"hk.dll");
   if(hMod!=NULL)
   {
       typedef LRESULT (__stdcall CALLBACK *_installhk)() ;
       _installhk installProc;
       installProc = (_installhk) GetProcAddress(hMod,"Install");
       if(installProc!=NULL)
       {
           installProc();
       }
   }

Во время отладки точки останова на KeyBoardHookProc ударил только один раз, когда я запускаю exe.

Программа продолжает работать, пока я не закрою ее, но если я введу что-нибудь еще с клавиатуры, процедура ловушки не будет вызвана.

В чем может быть причина этого?

Разве это не правильный способ настройки глобальной клавиатуры?

Ответы [ 6 ]

4 голосов
/ 25 января 2010

Как вы проверяли, что процедура ловушки не вызывается?Если вы пытались проверить его с помощью точки останова, вы должны позаботиться о том, чтобы ваша DLL-ловушка загружалась в каждом процессе, но ваша точка останова помещается только в ваш текущий процесс.сфокусируйтесь на нем перед нажатием клавиш или отладьте его с помощью журналов.

Другое решение - подключить WH_KEYBOARD_LL, который не требует дополнительной DLL.Вы можете подключиться прямо из вашего процесса.

2 голосов
/ 24 января 2010

Это может не иметь прямого отношения к вашей основной проблеме, но использование объекта CMyFile имеет несколько проблем:

  • Объект CMyFile выделяется динамически с помощью new CMyFile(...). Это создаст его только в памяти одного процесса.

  • Указатель pLF не инициализирован. Это означает, что он будет помещен в сегмент BSS вместо сегмента общих данных. Чтобы исправить это, объявите это с CMyFile *pLF = NULL;.

  • В самом CMyFile, вероятно, есть члены, содержащие файловые дескрипторы и / или указатели, которые не будут работать должным образом в других процессах.

Относительно вашего основного вопроса:

  • Кажется, вы правильно делаете крюк, насколько я вижу.

  • Нет необходимости приводить к HOOKPROC при вызове SetWindowsHookEx. Если вы получили предупреждение без него, проблема связана с типом вашей функции.

  • Нет необходимости в операторе if в обработчике ловушки - первый параметр CallNextHookEx в любом случае игнорируется в современной Windows, поэтому обе ветви эффективно выполняют одно и то же.

  • Я не знаю, доверял ли бы я точкам останова отладчика в подключаемой процедуре, вызываемой из разных процессов - возможно, что процедура вызывается, но отладчик не перехватывает ее.

2 голосов
/ 24 января 2010

Взгляните на код покойного Пола ДиЛасксии, который устанавливает глобальную клавиатуру для захвата клавиш Ctrl + Alt + Del, Диспетчер задач. MSDN сентябрь 2002 ' Отключение ключей в XP с помощью TrapKeys '

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

1 голос
/ 15 июня 2011

extern "C" хорошо, что избавится от искажения имени, упомянутого выше, но __stdcall будет конфликтовать с этим.

0 голосов
/ 25 мая 2011

Проверьте свой раздел экспорта для DLL и посмотрите, какое имя компоновщика экспортировало вашу функцию «Установить». C ++ искажает имена функций экспорта. Могу поспорить, что-нибудь, что это не «Установить», а _Install @ 12 или что-то в этом роде.

0 голосов
/ 24 января 2010

Вместо этого вы должны использовать API-вызов RegisterHoyKey - это намного меньше хлопот (как я недавно узнал, когда заменил аналогичную DLL-библиотеку хуков клавиатуры!).

...