12

キーダウンモーションのイベントを観察するために、このコードを書きました。問題は、このスクリプトを実行すると、特定のプログラムがこのプログラムをクラッシュさせ、次のエラー メッセージが表示されることです。

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

クラッシュが確認されたプログラムには、Skype、Sublime Text 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)

原因は何ですか?また、これを修正するにはどうすればよいですか?

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

PS初心者として、私はpythoncomの機能にあまり慣れておらず、オンラインの定義はかなり曖昧に見えます。pythoncom と PumpMessages の機能に関する説明をいただければ幸いです。

ありがとう

4

3 に答える 3

9

問題は、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);

ここではz、フォーマット文字列に があるため、win_name変数のデータは ASCII であるstrと想定して Unicode に変換されています。Py_BuildValueしかし、そうではありませんUnicodeDecodeError。これにより、が発生するarglistためNULL、関数は引数なしで呼び出されます。

したがって、ここでの最適な修正については完全にはわかりません。しかし、ASCII の代わりにワイド文字と Unicode を使用するように両方のコードを変更し、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 は 1 つです。

于 2015-10-26T23:10:40.450 に答える