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
There's a pyhook for python3: https://github.com/Answeror/pyhook_py3k This bug has been fixed in this project.
If only 1 out of each 2 presses works, it's definetely a problem with missing return value. Try returning either True or False.
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);
}
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);
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.
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);
}
and
// 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);
The problem occurs only with windows with non-ascii characters in their title: Skype is one.