I was curious how I spend my time and wanted something simple to log which window was active on my computer. I couldn’t see anything that did this easily on the internet, although there is a (more sophisticated/complicated) browsing history tracker, and I needed to relax for an hour or two so I thought I’d give it a shot in Python and see what came out. After looking at the flashing taskbar icon tutorial, how to get the currently active window, how to detect if Windows is idle and how to get rid of the console window, I could finally start programming. I really don’t know how people programmed before Google.
Python really makes things easy. It took less than 90 lines of code and just a couple hours to write this. So here is the code for it if you want to build it yourself:
[python] import wx from win32gui import GetWindowText, GetForegroundWindow from time import sleep, strftime, localtime from ctypes import windll, Structure, c_uint, sizeof, byref class TaskBarApp(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, -1, title, size = (1, 1), style=wx.FRAME_NO_TASKBAR|wx.NO_FULL_REPAINT_ON_RESIZE) self.ICON_STATE = 1 self.ID_ICON_TIMER=wx.NewId() self.tbicon = wx.TaskBarIcon() icon = wx.Icon(‘logon.ico’, wx.BITMAP_TYPE_ICO) self.tbicon.SetIcon(icon, ‘Logging’) self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDClick) self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarRightClick) self.Bind(wx.EVT_TIMER, self.Log, id=self.ID_ICON_TIMER) self.SetIconTimer() self.Show(True) self.lastInputInfo = self.LASTINPUTINFO() self.lastInputInfo.cbSize = sizeof(self.lastInputInfo) self.Write(self.Now()+”<|>__LOGGERSTART__<|>0\n”) def OnTaskBarLeftDClick(self, evt): if self.ICON_STATE == 0: self.Write(self.Now()+”<|>__LOGGERUNPAUSE__<|>0\n”) self.StartIconTimer() icon = wx.Icon(‘logon.ico’, wx.BITMAP_TYPE_ICO) self.tbicon.SetIcon(icon, ‘Logging’) self.ICON_STATE = 1 else: self.StopIconTimer() self.Write(self.Now()+”<|>__LOGGERPAUSE__<|>0\n”) icon = wx.Icon(‘logoff.ico’, wx.BITMAP_TYPE_ICO) self.tbicon.SetIcon(icon, ‘Not Logging’) self.ICON_STATE = 0 def OnTaskBarRightClick(self, evt): self.StopIconTimer() self.Write(self.Now()+”<|>__LOGGERSTOP__<|>0\n”) self.tbicon.Destroy() self.Close(True) wx.GetApp().ProcessIdle() def SetIconTimer(self): self.icontimer = wx.Timer(self, self.ID_ICON_TIMER) self.icontimer.Start(10000) def StartIconTimer(self): try: self.icontimer.Start(10000) except: pass def StopIconTimer(self): try: self.icontimer.Stop() except: pass def Log(self, evt): windll.user32.GetLastInputInfo(byref(self.lastInputInfo)) idleDelta = float(windll.kernel32.GetTickCount() – self.lastInputInfo.dwTime) / 1000 self.Write(self.Now()+”<|>“+GetWindowText(GetForegroundWindow())+”<|>“+str(idleDelta)+”\n”) def Write(self, text): f=open(‘log.tmp’, ‘a’) f.write (text) f.close() def Now(self): return strftime(“%Y-%m-%d %H:%M:%S”, localtime()) class LASTINPUTINFO(Structure): _fields_ = [(“cbSize”, c_uint),(“dwTime”, c_uint)] class MyApp(wx.App): def OnInit(self): frame = TaskBarApp(None, -1, ‘ ‘) frame.Center(wx.BOTH) frame.Show(False) return True def main(): app = MyApp(0) app.MainLoop() if __name__ == ‘__main__’: main() [/python]It’s not too pretty but it seems to work. If you try it, it should begin putting an entry in log.tmp
every ten seconds of ‘datetime<|>program title<|>idle time’. Unfortunately, it takes 16 megs of RAM. I guess there’s a lot going on in the background in the imported stuff. I think it would be much more efficient if programmed from scratch but I’m no programmer. Also, I would make an .exe for people without Python but the .dll files that would have to go along with it would take up more than 10 megs. Must be all the stuff going on in the background again. So it’s inefficient but it would get the job done if you want something quick for a day or two or maybe it could form the base of a more optimized program. Next time I have a little free time, I might write a program to read the log and make a summary.
Oh you’ll also need 2 32×32 .ico files called logon.ico and logoff.ico. You can use these or make your own icons.
|>|>|>|>|>|>|>|>|>|>
Ed Brannin | 07-Jul-09 at 5:08 pm | Permalink
Thanks for the script! I’m finding it useful. Two notes:
1. You can also hide the Console window by using “.pyw” instead of “.py” as the file extension.
2. The code here has a typo: the method that should be called StartIconTiemr() is actually a second copy of StopIconTimer().
ScottS-M | 08-Jul-09 at 8:06 am | Permalink
Glad it was useful. Let me know if you make any cool improvements. Thanks for catching the typo. I just fixed it above.
Shannon Wagner | 16-Aug-10 at 4:09 pm | Permalink
Thanks for sharing this! I am just starting out with Python, and have been looking for good examples of how to use some of the wxPython classes, like TaskbarIcon..
sam | 10-Feb-11 at 5:49 pm | Permalink
I have been trying to discover the environment you used to build and run this. the wx code seems limited to Python 2.7 (3.1 is current).. and I don’t know where the __win32gui__ stuff comes from.
running on xp.
thanks for any guidance
ScottS-M | 10-Feb-11 at 6:35 pm | Permalink
It was quite a while ago when I was playing with this. I guess it would definitely be a few versions back. It was on xp though.
sumanta | 15-Apr-16 at 8:17 am | Permalink
I am trying to run your above code in my win 7 machine with python 2.7 but I got the bellow error :
Traceback (most recent call last):
File “test.py”, line 77, in OnInit
frame = TaskBarApp(None, -1, ‘ ‘)
File “test.py”, line 11, in __init__
self.tbicon = wx.TaskBarIcon()
AttributeError: ‘module’ object has no attribute ‘TaskBarIcon’
OnInit returned false, exiting…
Can you please tell me what I have to do to get a error free output ?
ScottS-M | 27-Apr-16 at 12:43 pm | Permalink
Sorry sumanta, I wrote this quite a while ago and no longer have a windows machine to test things on. I’m not too sure what’s going on there.
vikram | 15-Dec-17 at 5:37 pm | Permalink
@sumanta
The TaskBarIcon class is moved from wx to wx.adv module in the recent wxPython package. To get this to work, Add this import statement
import wx.adv
and change the following lines..then it should work.
self.tbicon = wx.adv.TaskBarIcon()
………..
self.tbicon.Bind(wx.adv.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDClick)
self.tbicon.Bind(wx.adv.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarRightClick)
Make sure you download the logon.ico and logoff.ico files to your desktop and update the paths to these files in the code