首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >连接到某些应用程序时,pythoncom会在KeyDown上崩溃

连接到某些应用程序时,pythoncom会在KeyDown上崩溃
EN

Stack Overflow用户
提问于 2014-10-02 16:04:34
回答 3查看 7.4K关注 0票数 12

我写这段代码是为了观察按键运动的事件。问题似乎是,当运行此脚本时,某些程序将使此程序崩溃,并显示以下错误消息:

代码语言:javascript
复制
TypeError: KeyboardSwitch() missing 8 required positional arguments: 'msg', 'vk_
code', 'scan_code', 'ascii', 'flags', 'time', 'hwnd', and 'win_name'

观察到一些程序崩溃: Skype,Sublime Text 2

在调试了几次之后,问题似乎出现在最后一行,但我似乎无法缩小范围。我也不理解编译器返回的KeyboardSwitch()的含义……

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

代码语言:javascript
复制
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)

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

代码语言:javascript
复制
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的功能,我们将不胜感激。

谢谢

EN

回答 3

Stack Overflow用户

发布于 2015-10-27 07:10:40

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

代码语言:javascript
复制
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字符。然而,这不会失败,除非我们这样做:

代码语言:javascript
复制
// 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 str,其中Py_BuildValue假定它是ASCII码。但事实并非如此:因此它可以触发UnicodeDecodeError。这会导致arglistNULL,因此调用您的函数时不带参数。

所以我不能完全确定这里最好的修复方法。但我只是改变了这两段代码,使用宽字符和unicode,而不是ascii,并重新构建了pyHook,这似乎解决了它。我认为它只能在Python3版本中工作,但对于Python2,我认为旧的pyHook仍然可以工作。

代码语言:javascript
复制
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);
}

代码语言:javascript
复制
// 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就是其中之一。

票数 9
EN

Stack Overflow用户

发布于 2014-12-05 19:28:41

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

票数 0
EN

Stack Overflow用户

发布于 2017-11-03 11:05:25

有一个用于python3:https://github.com/Answeror/pyhook_py3k的pyhook,这个错误已经在这个项目中修复了。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26156633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档