#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
функции обратного вызова. Общий сегмент был кодом, оставшимся с того момента, когда я пытался использовать низкоуровневую клавиатуру. Прошу прощения за мой неаккуратный код, мне за это стыдно, но я исправлю это, прежде чем действительно начну его использовать. Еще раз, большое спасибо!