当使用钩到某些应用程序时,pythoncom在KeyDown上崩溃 [英] pythoncom crashes on KeyDown when used hooked to certain applications
问题描述
我写了这段代码以观察按下键盘的动作.问题似乎是当运行此脚本时,某些程序将导致该程序崩溃,并吐出此错误消息:
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 str
且Py_BuildValue
.但这不是:因此它可以触发UnicodeDecodeError
.然后,这将导致arglist
为NULL
,因此将在不带参数的情况下调用您的函数.
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屋!