Python:通过自定义系统级快捷键来控制程序开始或停止记录日志(使用小技巧解决一个貌似无解的问题)
2012-03-10 00:00
1321 查看
在之前写的一篇《Python:监控键盘输入、鼠标操作,并将捕获到的信息记录到文件中》文章中,有个读者留言如下:
这看似一个很平常的需求,但实现起来并不容易,如果用快捷键来控制一个程序干些别的事情那是非常容易的,但关键是本程序刚好是用hook来监控键盘,所以必须使用PumpMessages(),而此函数使用当前程序进入消息循环,它抓取每个鼠标和键盘事件。当我们的程序跑起来后,按下停止的热键时,也被此函数捕获,所以定义的任何热键均不能生效,具体实现及测试在文章《Python:通过自定义系统级快捷键来控制程序运行》中有所描述。
现在,我们换一个思路,既然已经监控到了按键,那就判断当前的按键是不是预先定义的热键,如果是,则可调用自己的处理函数,这样就找到了一个控制的入口,可以通过它实现我们想要的功能,注意此时不能让程序调用os.exit(0)让程序退出,否则再次按启动热键时就没法玩了。具体实现如下,代码中有详细注释,不再一一解释。
一、代码:
二、测试:
1、以下打印是按下热键时控制台输出(支持当前程序不是非激活窗口下按下热键)
2、日志内容:
可以看到,在23:16:58停止记录日志后,至23:17:05重新开始记录之前,所有的键盘和鼠标输入均没有记录,达到预期效果。
这看似一个很平常的需求,但实现起来并不容易,如果用快捷键来控制一个程序干些别的事情那是非常容易的,但关键是本程序刚好是用hook来监控键盘,所以必须使用PumpMessages(),而此函数使用当前程序进入消息循环,它抓取每个鼠标和键盘事件。当我们的程序跑起来后,按下停止的热键时,也被此函数捕获,所以定义的任何热键均不能生效,具体实现及测试在文章《Python:通过自定义系统级快捷键来控制程序运行》中有所描述。
现在,我们换一个思路,既然已经监控到了按键,那就判断当前的按键是不是预先定义的热键,如果是,则可调用自己的处理函数,这样就找到了一个控制的入口,可以通过它实现我们想要的功能,注意此时不能让程序调用os.exit(0)让程序退出,否则再次按启动热键时就没法玩了。具体实现如下,代码中有详细注释,不再一一解释。
一、代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- import pythoncom import pyHook import time import pyhk import os import sys import ctypes from ctypes import wintypes import win32con import win32api class CInspectKeyAndMouseEvent: ''' Function:键盘和鼠标监控类 Input:NONE Output: NONE author: socrates blog:http://blog.csdn.net/dyx1024 date:2012-03-09 ''' def __init__(self, filename): '初始化' self.filename = filename def open_file(self): '打开文件' self.fobj = open(self.filename, 'w') def close_file(self): '关闭文件' self.fobj.close() def IsNotWriteLog(self): '是否记录日志' return self.bFlag def IsExitCommand(self, event): ''' 是否当前按下了程序定义的热键' 如果按下了ALT+F2,将记录日志的状态位置为True,不记录日志, 如果按下了ALT+F1,将记录日志状态位置为False,表示记录日志 ''' if event.Alt == 32 and str(event.Key) == 'F2': self.bFlag = True print time.strftime('[%Y-%m-%d %H:%M:%S]: ',time.localtime(time.time()))+ ' stop write log' elif event.Alt == 32 and str(event.Key) == 'F1': self.bFlag = False print time.strftime('[%Y-%m-%d %H:%M:%S]: ',time.localtime(time.time()))+ ' start write log' def onMouseEvent(self, event): "处理鼠标事件" #判断是否要记录日志 if self.IsNotWriteLog(): return True self.fobj.writelines('-' * 20 + 'MouseEvent Begin' + '-' * 20 + '\n') self.fobj.writelines("Current Time:%s\n" % time.strftime('[%Y-%m-%d %H:%M:%S]: ',time.localtime(time.time()))) self.fobj.writelines("MessageName:%s\n" % str(event.MessageName)) self.fobj.writelines("Message:%d\n" % event.Message) self.fobj.writelines("Time_sec:%d\n" % event.Time) self.fobj.writelines("Window:%s\n" % str(event.Window)) self.fobj.writelines("WindowName:%s\n" % str(event.WindowName)) self.fobj.writelines("Position:%s\n" % str(event.Position)) self.fobj.writelines('-' * 20 + 'MouseEvent End' + '-' * 20 + '\n') return True def onKeyboardEvent(self, event): #处理按下的热键 self.IsExitCommand(event) #判断是否要记录日志 if self.IsNotWriteLog(): return True self.fobj.writelines('-' * 20 + 'Keyboard Begin' + '-' * 20 + '\n') self.fobj.writelines("Current Time:%s\n" % time.strftime('[%Y-%m-%d %H:%M:%S]: ',time.localtime(time.time()))) self.fobj.writelines("MessageName:%s\n" % str(event.MessageName)) self.fobj.writelines("Message:%d\n" % event.Message) self.fobj.writelines("Time:%d\n" % event.Time) self.fobj.writelines("Window:%s\n" % str(event.Window)) self.fobj.writelines("WindowName:%s\n" % str(event.WindowName)) self.fobj.writelines("Ascii_code: %d\n" % event.Ascii) self.fobj.writelines("Ascii_char:%s\n" % chr(event.Ascii)) self.fobj.writelines("Key:%s\n" % str(event.Key)) self.fobj.writelines('-' * 20 + 'Keyboard End' + '-' * 20 + '\n') return True #默认记录 bFlag = False def InspectKeyAndMouseEvent(): "启动监控" my_event = CInspectKeyAndMouseEvent("D:\\hook_log.txt") my_event.open_file() #创建hook句柄 hm = pyHook.HookManager() #监控键盘 hm.KeyDown = my_event.onKeyboardEvent hm.HookKeyboard() #监控鼠标 hm.MouseAll = my_event.onMouseEvent hm.HookMouse() #循环获取消息 pythoncom.PumpMessages() my_event.close_file() def handle_start_InspecEvent(): "开始监控(按下Ctrl + F1)" print time.strftime('[%Y-%m-%d %H:%M:%S]: ',time.localtime(time.time()))+ ' start write log' InspectKeyAndMouseEvent() #def handle_stop_InspecEvent(): # "停止监控 (按下Ctrl + F2)" # InspectKeyAndMouseEvent(False) if __name__ == "__main__": ''' Function:通过快捷键控制程序运行 Input:NONE Output: NONE author: socrates blog:http://blog.csdn.net/dyx1024 date:2012-03-09 ''' byref = ctypes.byref user32 = ctypes.windll.user32 #定义快捷键 HOTKEYS = { 1 : (win32con.VK_F1, win32con.MOD_ALT) # 2 : (win32con.VK_F2, win32con.MOD_ALT) } #快捷键对应的驱动函数 HOTKEY_ACTIONS = { 1 : handle_start_InspecEvent, # 2 : handle_stop_InspecEvent } #注册快捷键 for id, (vk, modifiers) in HOTKEYS.items (): if not user32.RegisterHotKey (None, id, modifiers, vk): print "Unable to register id", id #启动监听 try: msg = wintypes.MSG () while user32.GetMessageA (byref (msg), None, 0, 0) != 0: if msg.message == win32con.WM_HOTKEY: action_to_take = HOTKEY_ACTIONS.get (msg.wParam) if action_to_take: action_to_take () user32.TranslateMessage (byref (msg)) user32.DispatchMessageA (byref (msg)) finally: for id in HOTKEYS.keys (): user32.UnregisterHotKey (None, id)
二、测试:
1、以下打印是按下热键时控制台输出(支持当前程序不是非激活窗口下按下热键)
2、日志内容:
可以看到,在23:16:58停止记录日志后,至23:17:05重新开始记录之前,所有的键盘和鼠标输入均没有记录,达到预期效果。
--------------------MouseEvent Begin-------------------- Current Time:[2012-03-09 23:16:57]: MessageName:mouse move Message:512 Time_sec:12542031 Window:328916 WindowName:FolderView Position:(737, 438) --------------------MouseEvent End-------------------- --------------------Keyboard Begin-------------------- Current Time:[2012-03-09 23:16:58]: MessageName:key sys down Message:260 Time:12542890 Window:1639322 WindowName:本地磁盘 (D:) Ascii_code: 0 Ascii_char: Key:Lmenu --------------------Keyboard End-------------------- --------------------Keyboard Begin-------------------- Current Time:[2012-03-09 23:17:05]: MessageName:key sys down Message:260 Time:12550015 Window:1639322 WindowName:本地磁盘 (D:) Ascii_code: 0 Ascii_char: Key:F1 --------------------Keyboard End-------------------- --------------------MouseEvent Begin-------------------- Current Time:[2012-03-09 23:17:06]: MessageName:mouse move Message:512 Time_sec:12551000 Window:328916 WindowName:FolderView Position:(720, 420) --------------------MouseEvent End-------------------- --------------------MouseEvent Begin-------------------- Current Time:[2012-03-09 23:17:06]: MessageName:mouse move Message:512 Time_sec:12551015 Window:328916 WindowName:FolderView Position:(719, 420) --------------------MouseEvent End--------------------
相关文章推荐
- Python:通过自定义系统级快捷键来控制程序开始或停止记录日志(使用小技巧解决一个貌似无解的问题)
- Python:通过自定义系统级快捷键来控制程序运行
- Python:通过自定义系统级快捷键来控制程序运行
- Web项目中使用NLog记录日志,利用单件模式控制整个项目只有一个Logger对象的问题
- 请教一个问题,Log4Net记录日志到Oracle显示中文乱码如何解决?
- CSDN博客:对于一个程序员,写程序就是实现功能,遇到具体问题,解决这个问题,并记录问题到CSDN上,从而有所提高和互相帮助。
- Python调用不在同一个文件夹下的Python程序,并且如何解决pyinstaller打包路径问题
- 解决通过Intent调用系统拍照程序,返回图片太小的问题[android] 【转】
- 一个关于时间的故事(通过历史分析解决程序问题)
- 使用VS进行打包程序解决生成两个文件的问题(压缩后只有一个exe)
- linux Eclipse上c++调用使用了tensorflow库的python程序遇到的问题及解决方法
- Liferay使用第三方权限系统控制Portlet权限问题记录
- Porteus基于Slackware发行版,系统声音问题的解决(通过万能的google解决的,在此记录一下)
- 使用LOG4J记录程序日志的一个例子
- 使用自定义注解和切面记录系统日志
- 记录使用python时遇到的中文 编码问题与解决方法
- 解决eclipse使用Python插件程序乱码问题
- Android 通过Intent调用系统拍照程序出现图片太小的问题解决办法
- 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
- 解决通过Intent调用系统拍照程序,返回图片太小的问题[android]