当钩子连接到某些应用程序时,pythoncom在KeyDown上崩溃

 李2502933835 发布于 2022-12-18 17:32

我写了这段代码来观察keydown动作的事件.问题似乎是,当运行此脚本时,某些程序将使此程序崩溃,并吐出此错误消息:

TypeError: KeyboardSwitch() missing 8 required positional arguments: 'msg', 'vk_
code', 'scan_code', 'ascii', 'flags', 'time', 'hwnd', and 'win_name'

一些被发现崩溃的程序是:Skype,Sublime Text 2

在调试它的几次试验之后,问题似乎发生在最后一行,但我似乎无法缩小范围.我也不明白编译器返回的KeyboardSwitch()的含义......

我还发现程序会交替返回此错误消息

Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\pyHook\HookManager.py", line 351, in KeyboardSwitch
    return func(event)
  File "observe.py", line 6, in OnKeyboardEvent
    print ('MessageName:',event.MessageName)
TypeError: an integer is required (got type NoneType)

原因是什么以及如何解决这个问题,特别是因为它只出现在按下的两个键中

import pyHook, pythoncom

def OnKeyboardEvent(event):
# Source: http://code.activestate.com/recipes/553270-using-pyhook-to-block-windows-keys/ 
    print ('MessageName:',event.MessageName)
    print ('Message:',event.Message)
    print ('Time:',event.Time)
    print ('Window:',event.Window)
    print ('WindowName:',event.WindowName)
    print ('Ascii:', event.Ascii, chr(event.Ascii))
    print ('Key:', event.Key)
    print ('KeyID:', event.KeyID)
    print ('ScanCode:', event.ScanCode)
    print ('Extended:', event.Extended)
    print ('Injected:', event.Injected)
    print ('Alt', event.Alt)
    print ('Transition', event.Transition)
    print ('---')

hooks_manager = pyHook.HookManager()
hooks_manager.KeyDown = OnKeyboardEvent
hooks_manager.HookKeyboard()
pythoncom.PumpMessages()

PS作为初学者,我对pythoncom的功能不是很熟悉,在线定义似乎相当含糊.关于pythoncom和PumpMessages功能的解释将不胜感激.

谢谢

1 个回答
  • 我认为问题在于,当Windows调用pyHook时,它首先要做的是获取具有焦点的窗口的窗口名称.

    PSTR win_name = NULL;
    ...
    // grab the window name if possible
    win_len = GetWindowTextLength(hwnd);
    if(win_len > 0) {
      win_name = (PSTR) malloc(sizeof(char) * win_len + 1);
      GetWindowText(hwnd, win_name, win_len + 1);
    }
    

    所以我认为这里的问题是,即使GetWindowText没有返回宽字符,它也可以从ANSI代码页返回非ascii字符.但是,在我们这样做之前,这不会失败:

    // pass the message on to the Python function
    arglist = Py_BuildValue("(iiiiiiiz)", wParam, kbd->vkCode, kbd->scanCode, ascii,
                            kbd->flags, kbd->time, hwnd, win_name);
    

    这里,由于z格式字符串,win_name变量中的数据被转换为unicode str,Py_BuildValue假设它是ASCII.但它不是:所以它可以触发一个UnicodeDecodeError.这就导致arglistNULL,因此你的函数不带参数调用.

    所以我不完全确定这里最好的解决方案.但我只是改变了两个代码来使用宽字符和unicode而不是ascii,并重建了pyHook,这似乎解决了它.我认为它只适用于Python 3版本,但对于Python 2,我认为旧的pyHook仍然可以工作.

    LPWSTR win_name = NULL;
    
    ...
    // grab the window name if possible
    win_len = GetWindowTextLengthW(hwnd);
    if(win_len > 0) {
      win_name = (LPWSTR) malloc(sizeof(wchar_t) * win_len + 1);
      GetWindowTextW(hwnd, win_name, win_len + 1);
    }
    

    // pass the message on to the Python function
    arglist = Py_BuildValue("(iiiiiiiu)", wParam, kbd->vkCode, kbd->scanCode, ascii,
                            kbd->flags, kbd->time, hwnd, win_name);
    

    只有在标题中包含非ascii字符的窗口才会出现此问题:Skype是一个.

    2022-12-18 17:33 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有