pyHook KeyLogger线程未完成

时间:2014-05-07 11:08:24

标签: python multithreading python-multithreading pyhook

我为一个键盘记录器创建了一个线程,该线程与另一个产生一些声音的线程并行记录(我希望捕获反应时间)。

不幸的是,虽然我调用了killKey()并且打印了“invoked killkey()”,但线程永远不会完成。

我总是从这个帖子中得到一个thread.isActive()= true。

class KeyHandler(threading.Thread):
    hm = pyHook.HookManager()

    def __init__(self): 
       threading.Thread.__init__(self) 

    def OnKeyboardCharEvent(self,event):
        print 'Key:', event.Key
        if event.Key=='E':
            ...   
        return True

    def killKey(self):
        KeyHandler.hm.UnhookKeyboard() 
        ctypes.windll.user32.PostQuitMessage(0) 
        print "invoked killkey()"

    def run(self):
        print "keyHandlerstartetrunning"
        KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
        KeyHandler.hm.HookKeyboard()
        #print "keyboardhooked"
        pythoncom.PumpMessages()

更确切地说, ctypes.windll.user32.PostQuitMessage(0)什么都不做

我赞成使用外部超时来调用此线程中的killKey()和相应的ctypes.windll.user32.PostQuitMessage(0)。

2 个答案:

答案 0 :(得分:2)

PostQuitMessage必须从同一个帖子发布。为此,您需要引入全局变量STOP_KEY_HANDLER。如果你想退出,那么只需从你想要的任何线程设置全局STOP_KEY_HANDLER = True,它将在下一次击键时退出。您的密钥处理程序必须在主线程上运行。

STOP_KEY_HANDLER = False

def main():
    pass # here do all you want
    #bla bla
    global STOP_KEY_HANDLER
    STOP_KEY_HANDLER = True # This will kill KeyHandler


class KeyHandler:
    hm = pyHook.HookManager()

    def OnKeyboardCharEvent(self,event):
        if STOP_KEY_HANDLER:
            self.killKey()
        print 'Key:', event.Key
        if event.Key=='E':
            pass
        return True

    def killKey(self):
        global STOP_KEY_HANDLER
        if not STOP_KEY_HANDLER:
            STOP_KEY_HANDLER = True
            return None
        KeyHandler.hm.UnhookKeyboard()
        ctypes.windll.user32.PostQuitMessage(0)
        print "invoked killkey()"

    def _timeout(self):
        if self.timeout:
            time.sleep(self.timeout)
            self.killKey()

    def run(self, timeout=False):
        print "keyHandlerstartetrunning"
        self.timeout = timeout
        threading.Thread(target=self._timeout).start()

        KeyHandler.hm.KeyDown = self.OnKeyboardCharEvent
        KeyHandler.hm.HookKeyboard()
        #print "keyboardhooked"
        pythoncom.PumpMessages()


k=KeyHandler()

threading.Thread(target=main).start()
k.run(timeout=100) # You can specify the timeout in seconds or you can kill it directly by setting STOP_KEY_HANDLER to True.

答案 1 :(得分:1)

我猜pbackup的解决方案很好。只是得出结论我通过简单地自己发送密钥而不是等待用户输入来找到解决方案。它可能不是最好的,但是在我的计时线程中与其他计时程序并行最快。

    STOP_KEY_HANDLER = True

    # send key to kill handler - not pretty but works
    for hwnd in get_hwnds_for_pid (GUIWINDOW_to_send_key_to.pid):
        win32gui.PostMessage (hwnd, win32con.WM_KEYDOWN, win32con.VK_F5, 0)
    # sleep to make sure processing is done
    time.sleep(0.1)

    # kill window
    finished()