【问题标题】:KeyboardHookProc in DLL doesn't do anything when called from python从 python 调用时,DLL 中的 KeyboardHookProc 不执行任何操作
【发布时间】:2011-08-03 11:18:59
【问题描述】:

我一直在尝试用 C 编写一个 DLL。

安装挂钩设置 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 方面的专家,因此我们将不胜感激。谢谢。

【问题讨论】:

    标签: python c winapi dll hook


    【解决方案1】:
    hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0);
    

    SetWindowsHookEx 需要一个 hModule - 从 DllMain 保存 hModule 并在此处传递。 (只有当线程 id 是您自己的线程时,您才能传递 NULL。)

    _LL 钩子类型是一个例外;这些不需要 hmodule 参数,因为这些钩子不会注入目标进程 - 这就是为什么使用 KEYBOARD_LL 的代码“成功”的原因。

    至于为什么当你使用 KEYBOARD_LL 时它可能会阻塞 - LowLevelKeyboardHookProc 的文档提到安装钩子的线程(即调用 SetWindowsHookEx)必须有一个消息循环,而你的 python 代码中可能没有。

    p>

    调试提示:看起来 SetWindowsHookEx 应该返回 NULL(GetLastError() 返回合适的错误代码);在开发代码时,适当地使用 assert/printf/OutputDebugString 的某种组合来检查这些返回值是确保您的假设正确并为您提供一些关于哪里出错的线索的好方法。

    顺便说一句,KEYBOARD 与 KEYBOARD_LL 的另一件事是:KEYBOARD 挂钩被加载到目标进程中 - 但前提是它的位数相同 - 所以 32 位挂钩只能看到其他 32 位进程按下的键. OTOH,KEYBOARD_LL 在您自己的进程中被回调,因此您可以查看所有键 - 并且也不需要处理共享段(尽管据我所知,它作为 KEYBOARD 挂钩的效率也较低)。

    【讨论】:

    • 你是对的!我需要从 DLLMain 中保存 HMODULE 类型。它现在在KeyboardProc 回调函数中增加我的keypresses 值。共享段是我尝试低级键盘时留下的代码。为我草率的代码道歉,我为它感到羞耻,但我会在我真正开始使用它之前修复它。再次,非常感谢!
    猜你喜欢
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多