KeyboardHookProc в DLL ничего не делает при вызове из python - PullRequest
0 голосов
/ 12 апреля 2011

Я пытался написать DLL на C.

Установочный хук устанавливает KeyboardProc. Вызов функций InstallHook() и UninstallHook() из Python всегда возвращает 0, что, я думаю, объясняется тем, что моя функция обратного вызова KeyboardProc не работает.

Ниже приведен мой C-код для DLL:

#include "stdafx.h"
#include <windows.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "ourdll.h"

//#pragma comment(linker, "/SECTION:.SHARED,RWS")
//#pragma data_seg(".SHARED")
HHOOK hKeyboardHook = 0;
int keypresses = 0;
    HMODULE hInstance = 0;

//#pragma data_seg()

BOOL WINAPI DllMain (HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
            hInstance = hModule;  //Edit
    return TRUE;
}

LRESULT CALLBACK KeyboardProc(int hookCode, WPARAM vKeyCode, LPARAM flags)
{
    if(hookCode < 0)
    {
        return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
    }

    keypresses++;;

    return CallNextHookEx(hKeyboardHook, hookCode, vKeyCode, flags);
}

__declspec(dllexport) void InstallHook(void)
{
    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
}

__declspec(dllexport) int UninstallHook(void)
{
    UnhookWindowsHookEx(hKeyboardHook);
    hKeyboardHook = 0;
    return keypresses;
}

Код Python для его использования выглядит следующим образом:

>>> from ctypes import *
>>> dll = CDLL('C:\...\OurDLL.dll')
>>> dll.InstallHook()

[Наберите что-нибудь в этот момент]

>>> result = dll.UninstallHook()
>>> result
0

РЕДАКТИРОВАТЬ: Я должен, вероятно, упомянуть, что я также опробовал LowLevelKeyboardHook. Я понимаю, что хук LowLevel является глобальным и отлавливает все нажатия клавиш, но это только заставило мой dll.InstallHook() код Python зависнуть на секунду или две, прежде чем вернуть ноль.

Я не эксперт в Си, поэтому любая помощь будет принята с благодарностью. Спасибо.

1 Ответ

1 голос
/ 12 апреля 2011
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);

SetWindowsHookEx требует hModule - сохраните hModule из DllMain и передайте его здесь. (Вы можете передать NULL, только если идентификатор потока является вашим собственным потоком.)

Единственное исключение - для типов ловушек _LL; они не нуждаются в параметре hmodule, так как эти ловушки не внедряются в целевой процесс - вот почему ваш код, использующий KEYBOARD_LL, является «успешным».

Что касается того, почему он может блокироваться, когда вы используете KEYBOARD_LL - в документах для LowLevelKeyboardHookProc упоминается, что поток, который устанавливает ловушку (т. Е. Вызывает SetWindowsHookEx), должен иметь цикл сообщений, которого вы могли бы не иметь в своем коде python.

Советы по отладке: похоже, SetWindowsHookEx должен возвращать NULL (с ​​GetLastError () возвращает подходящий код ошибки); при разработке кода использование некоторой комбинации assert / printf / OutputDebugString в зависимости от ситуации, чтобы проверить эти возвращаемые значения, является хорошим способом убедиться, что ваши предположения верны и дать вам некоторые подсказки относительно того, где что-то идет не так.

Кстати, еще одна вещь, на которую нужно обратить внимание при использовании KEYBOARD против KEYBOARD_LL: хук KEYBOARD загружается в целевой процесс - но только если он имеет ту же разрядность - так что 32-битный хук видит только клавиши, нажатые другими 32-битными процессами , OTOH, KEYBOARD_LL вызывается обратно в вашем собственном процессе, так что вы можете увидеть все ключи - и также не нужно иметь дело с общим сегментом (хотя, насколько я знаю, он также менее эффективен в качестве хука KEYBOARD).

...