DLL中的KeyboardHookProc从python调用时不执行任何操作

时间:2011-04-11 23:08:40

标签: python c winapi dll hook

我一直在尝试用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的专家,所以任何帮助都将不胜感激。感谢。

1 个答案:

答案 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钩子效率较低)。