当使用钩到某些应用程序时,pythoncom在KeyDown上崩溃 [英] pythoncom crashes on KeyDown when used hooked to certain applications

查看:175
本文介绍了当使用钩到某些应用程序时,pythoncom在KeyDown上崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了这段代码以观察按下键盘的动作.问题似乎是当运行此脚本时,某些程序将导致该程序崩溃,并吐出此错误消息:

I wrote this code on to observe the event of a keydown motion. The problem appears to be that when this script is run, certain programs will crash this program, spitting out this error message:

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

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

Some programs observed to crash are: Skype, Sublime Text 2

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

After a few trials at debugging it, the problem appears to be occurring on the final line but I can't seem to narrow it down. I also don't understand the meaning of KeyboardSwitch() as returned by the compiler...

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

I have also found that the program would alternately return this error message

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个出现了

What is the cause and how do I fix this, especially since it only appears for only 1 in 2 keys pressed

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

P.S.作为一个初学者,我对pythoncom的功能不是很熟悉,并且在线定义似乎还很模糊.对pythoncom和PumpMessages功能的解释将不胜感激.

P.S. As a beginner, I'm not very familiar with the function of pythoncom and the online definitions appear to be rather vague. An explanation on the function of pythoncom and PumpMessages would be greatly appreciated.

谢谢

推荐答案

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

I think the problem is that when pyHook gets called back by Windows, the first thing it does is get the window name for the window with focus.

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字符.但是,除非我们这样做,否则这不会失败:

So I think the problem here is that, even if GetWindowText is not returning wide characters, it can return non-ascii characters from an ANSI codepage. That won't fail, however, until we do this:

// 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变量中的数据是ASCII码,则将其转换为Unicode strPy_BuildValue.但这不是:因此它可以触发UnicodeDecodeError.然后,这将导致arglistNULL,因此将在不带参数的情况下调用您的函数.

Here, because of the z in the format string, the data in the win_name variable is being converted to a unicode str with Py_BuildValue assuming it is ASCII. But it's not: and so it can trigger a UnicodeDecodeError. This then causes the arglist to be NULL and therefore your function to be called with no arguments.

因此,我不太确定此处的最佳解决方案.但是我只是更改了两位代码,以使用宽字符和unicode而不是ascii,并重建了pyHook,这似乎可以解决问题.我认为它仅适用于Python 3版本,但对于Python 2,我认为仍然可以使用旧的pyHook.

So I'm not completely sure on the best fix here. But I just changed both bits of code to use wide characters and unicode instead of ascii, and rebuilt pyHook, and that seemed to fix it. I think it will only work in Python 3 versions, but for Python 2, I think the old pyHook still works anyway.

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是其中一个.

The problem occurs only with windows with non-ascii characters in their title: Skype is one.

这篇关于当使用钩到某些应用程序时,pythoncom在KeyDown上崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆