我一直在尝试用C语言编写DLL。
Install hook设置KeyboardProc。从Python调用InstallHook()
和UninstallHook()
函数总是返回0,我想这是因为我的回调函数KeyboardProc
无效。
以下是我的DLL的C代码:
#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代码在返回零之前冻结一两秒。
我不是C的专家,所以任何帮助都将不胜感激。感谢。
答案 0 :(得分:1)
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);
SetWindowsHookEx需要一个hModule - 从DllMain保存hModule并将其传递给此处。 (只有当线程id是您自己的线程时,才能传递NULL。)
一个例外是_LL钩子类型;这些不需要hmodule参数,因为这些钩子不会注入到目标进程中 - 这就是使用KEYBOARD_LL的代码“成功”的原因。
为什么在使用KEYBOARD_LL时它可能会阻塞 - 对于LowLevelKeyboardHookProc的文档提到安装钩子的线程(即调用SetWindowsHookEx)必须有一个消息循环,你可能没有在你的python代码中。
调试提示:看起来SetWindowsHookEx应该返回NULL(GetLastError()返回一个合适的错误代码);在开发代码时,使用assert / printf / OutputDebugString的某种组合来检查这些返回值是一种很好的方法,可以确保你的假设是正确的,并为你提供一些关于出错的地方的线索。
BTW,用KEYBOARD和KEYBOARD_LL注意另外一件事:KEYBOARD挂钩被加载到目标进程中 - 但只有当它具有相同的位数时 - 所以32位挂钩只能看到其他32位进程按下的键。 OTOH,KEYBOARD_LL在你自己的进程中被回调,所以你可以看到所有的键 - 也不需要处理共享段(尽管据我所知它也作为KEYBOARD钩子效率较低)。