pythoncom挂接到某些应用程序时在KeyDown上崩溃

bfnvny8b  于 2022-12-20  发布在  Python
关注(0)|答案(4)|浏览(90)

我写这段代码是为了观察按键动作的情况,问题是当这个脚本运行时,某些程序会使这个程序崩溃,并弹出以下错误消息:

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

观察到的一些崩溃程序是:Skype,崇高的文本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)

原因是什么,我如何解决这个问题,特别是因为它只出现在只有1/2的键按下

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()

作为一个初学者,我对pythoncom的功能不是很熟悉,网上的定义也很模糊。如果能解释一下pythoncom和PumpMessages的功能,我将不胜感激。
谢啦,谢啦

2q5ifsrm

2q5ifsrm1#

我认为问题在于,当pyHook被Windows回调时,它所做的第一件事就是获取具有焦点的窗口的窗口名。

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);

在这里,由于格式字符串中的zwin_name变量中的数据被转换为unicode strPy_BuildValue假设它是ASCII,但它不是:所以它可以触发一个UnicodeDecodeError,这会导致arglist变成NULL,这样你的函数就不用参数被调用了。
所以我并不完全确定最好的修复方法,但是我只是将代码的两部分都改为使用宽字符和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就是其中之一。

egmofgnx

egmofgnx2#

如果2次按下中只有1次有效,则肯定是缺少返回值的问题。请尝试返回True或False。

mkshixfv

mkshixfv3#

类型错误:KeyboardSwitch()缺少8个必需的位置参数:“msg”、“vk_code”、“scan_code”、“ascii”、“flags”、“time”、“hwnd”和“win_name”错误消息表示您正在尝试调用名为KeyboardSwitch的函数,并且尚未提供所有必需参数的值。
错误消息将所需参数列出为“msg”、“vk_code”、“scan_code”、“ascii”、“flags”、“time”、“hwnd”和“win_name”。这些是KeyboardSwitch函数在被调用时希望接收的参数名称。在调用该函数时,必须按正确顺序为每个参数提供值。
若要修复此错误,您需要确保在调用KeyboardSwitch函数时为所有必需参数提供了值。您可能还需要检查KeyboardSwitch函数的文档,以确保正确使用该函数并了解每个必需参数所表示的内容。

kuuvgm7e

kuuvgm7e4#

python3有一个pyhook:https://github.com/Answeror/pyhook_py3k此错误已在此项目中修复。

相关问题