Python pyhook

From wikinotes
http://pyhook.sourceforge.net/doc_1.5.0/ Official PyHook API

pyHook uses the pyWin32 module to intercept keypress events. You can simply read them, bind your own custom actions, disable some actions etc. The standard way of getting keypress events is by using pythoncom.PumpMessages(). This creates an endless loop within Windows' eventLoop, that does not quit until a WM_QUIT message is sent to the thread. For this reason, in the example I am starting a the call to pythoncom.PumpMessages in a separate thread, so that I can run a timer, and disable it when I am ready.


Mouse Events

import pythoncom, pyHook
import logging

def mouseEvent(event ):
	import logging

	print 'MessageName:'  , event.MessageName
	print 'Message:'      , event.Message
	print 'Time:'         , event.Time
	print 'Window:'       , event.Window
	print 'WindowName:'   , event.WindowName
	print 'Position:'     , event.Position
	print 'Wheel:'        , event.Wheel
	print 'Injected:'     , event.Injected
	print '---'

	logging.info( 'MousePosition: '+ str(event.Position) )
	
	return True


Keyboard Events

import pythoncom, pyHook
import logging

## Monitor Keypress Events
def keyDownEvent(event):
	import win32api
	import logging

	mainThread = win32api.GetCurrentThreadId()

	print 'MessageName:' , event.MessageName
	print 'Message:'     , event.Message
	print 'Time:'        , event.Time
	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 '---'

	logging.info( 'Ascii:' +' '+ chr(event.Ascii) )

	return True


Main Loop

def makeHook( index=None, threadTracker=None ):
	""" Loop To Monitor all keystrokes/mouse movements """
	import win32api

	## Get win32 ThreadId (so we can kill it later)
	threadId = win32api.GetCurrentThreadId()
	threadTracker.threads[ index ] = threadId

	## Start Monitoring Events
	hook          = pyHook.HookManager()
	hook.MouseAll = mouseEvent
	hook.KeyDown  = keyDownEvent
	hook.HookMouse()
	hook.HookKeyboard()
	pythoncom.PumpMessages()


ThreadTracker

class ThreadTracker(object):
	""" Common Object to store win32ThreadIds """
	def __init__(self):
		self.threads = {}				## Dict of assignedIndex:win32_threadId


Run Threaded

if __name__ == '__main__':

	import win32api
	import win32con
	import time
	import threading
	import logging
	

	## Logging
	logging.basicConfig( 
			filename = 'C:/Users/willp/Desktop/dev/pyhook/pyhook.log',
			level    = logging.DEBUG,
			)
	logging.info( 'Press Any Key, or Move the Mouse to write to the log'     )
	logging.info( 'This must be run directly from the CLI, and not ipython.' )



	## Create Object to track Threads
	trackerObj = ThreadTracker()
	
	## Run win32Hook in a separate thread (so we can continue working here)
	index = 0
	t = threading.Thread( 
				target = makeHook,
				args   = ( index, trackerObj, ),
			)
	t.start()
	


	## In order to send stop PumpMessages from monitoring all
	## events, you need to send a 'WM_QUIT' message to the process' thread
	## In order to do this, you need to capture it's threadId.
	
	## Wait 2 seconds, then kill the thread
	time.sleep( 5 )
	win32api.PostThreadMessage( 
			trackerObj.threads[ index ] ,
			win32con.WM_QUIT            ,
			0                           ,
			0                           ,
		)