KeyboardHookProc в DLL ничего не делает при вызове из python

#python #c #winapi #dll #hook

#python #c #winapi #dll #перехват

Вопрос:

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

Install hook настраивает 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 . Я понимаю, что низкоуровневый хук является глобальным и будет перехватывать все нажатия клавиш, но это просто заставило мой dll.InstallHook() код Python зависнуть на секунду или две, прежде чем вернуть ноль.

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

Ответ №1:

 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);
  

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

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

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

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

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

Комментарии:

1. Вы правы! Мне нужно было сохранить HMODULE тип из DllMain. Теперь он увеличивает мое keypresses значение в KeyboardProc функции обратного вызова. Общий сегмент был кодом, оставшимся с того момента, когда я пытался использовать низкоуровневую клавиатуру. Прошу прощения за мой неаккуратный код, мне за это стыдно, но я исправлю это, прежде чем действительно начну его использовать. Еще раз, большое спасибо!