How to create a time tracking application on Windows with AutoHotKey


You start work every day early so you can handle everything for the day. Then, you check the clock, it’s 3 am but the work is still not done. So where has the time gone?

You can use a dedicated time tracking app, but these apps can be complicated and frustrating. Instead, why not create a simple little app of your own? This application can keep track of all the windows you have used during the day. You only need AutoHotKey, a basic word processor like Notepad, and about half an hour. Let’s get started!

Create your own window logging script with AutoHotKey

Before you start, you should install AHK on your computer as it will act as the “parser” for the script. It’s the tool that will allow your script to “run”.

Note: You can also compile the script once it’s done to turn it into a real executable. However, that is beyond the scope of this article.

Download AutoHotKey from the official website and install it.

AutoHotKey Script” width=”650″ height=”388″ class=”lazy” data-src=”https://st.quantrimang.com/photos/image/2021/11/23/tao-ung-dung-theo-doi-thoi-gian-windows-voi-autohotkey-1.jpg”/>
Select New > AutoHotKey Script

Fire up your favorite file manager and go to the folder where you want to store the script. Then right click on an empty spot and select New > AutoHotKey Script.

Once done, it’s time to write the actual script.

1. Define the required variables

Open the script in your favorite editor. You can use something as simple as Notepad that comes with Windows, but the article will use Notepad++ for this tutorial. Notepad++ is free and better adapted for this purpose, so you should give it a try.

Note that you should not use any applications such as Word or Google Docs, this may affect the formatting of the script. Use a text or code editor.

The script will contain some basic recommended information about compatibility and performance. Leave them as is and start the script below.

Starts with:

AppLoggingRate = 10 ; Time interval (in seconds) between active window title captures.
SleepTime := AppLoggingRate * 1000
LogPath = %A_ScriptDir%
LastActiveWindow =

Start by assigning the value “ten” give AppLoggingRate, this value will be used to calculate the time between window logging.

When used with the AHK’s Sleep function, 1000 is close to one second. So by multiplying it by AppLogingRate, you would make the SleepTime variable “equal to 10 seconds”.

LogPath is the path used to store the records. The example is using the value %A_ScriptDir%, this value is translated to “the directory from where you run the script”. You can use the full path to another directory if you want.

Finally, put LastActiveWindow to blank and use the following to check if the active window has changed.

2. Monitor active windows

Since we want to continuously monitor which window is active and, if it changes, record the title and time, we will have to use a “loop”.

As the name suggests, a loop runs continuously, repeating the same function(s). Thanks to AHK’s simple syntax, the following “code” is relatively easy to understand:

Loop
{
    Sleep %SleepTime%
    Msgbox, It Works!
}

Define a loop by simply typing the word “loop” and then marking its beginning with “{“ and ends with “}”. Everything in the middle lines “{“ and “}” will run forever until you exit the script.

Start the loop by waiting (Sleep) for a time equal to the variable SleepTime. This variable makes time control simpler. Instead of manually editing the script, you can “tell” it, through this variable, how many seconds each loop should last.

Finally, use Message Box to test scripts. Try saving and running it (double click on the script file). You will see a message box that says “It Works!” (script is working) after 10 seconds.

Right click on the icon of AHK in the Windows tray and exit the script when you have enough message boxes. Then go back to the editor and replace the line MsgBox equal:

WinGetActiveTitle, ActiveWindow

This is the command to get the title of the active window. Skip the line “StoreActiveWindow” plugins that the example used while writing the test script.

Get the active window's title and store it in a variable
Get the active window’s title and store it in a variable

3. Get current time and name

Now to the core of the script logic. Compare the active window’s name with the previous one, and if they’re different, “do something”. Everything is as simple as this:

If ActiveWindow != %LastActiveWindow%
{
}

With the above, check that ActiveWindow There are currently other (!=) with the value stored in the variable LastActiveWindow (which was initially set to blank) or not. If so, AHK will execute the code between { and }, is currently empty.

Set the function to compare the title of the active window and the previous window
Set the function to compare the title of the active window and the previous window

Both date and time are needed to measure the uptime of a window. Different logs for each day, using the date in their name will be kept. Not only every change but when it happens will also be recorded. To do that, assign different time formats to the variables LogTime and LogFilename, with:

FormatTime, LogTime,, HH:mm:ss
FormatTime, LogFilename,, yyyy-MMM-dd

Add those lines between the curly braces in “If ActiveWindow…”, so that AHK runs them when a window change is detected.

Get the current time and assign it in two variables of different format
Get the current time and assign it in two variables of different format

4. Data Format

We have now captured the time in two differently formatted variables, as well as the title of the active window. However, there is a small problem: The title of the window can also contain unwanted characters. All non-alphanumeric characters can be removed using AHK’s support for RegEx, with:

LogWindow := Regexreplace(ActiveWindow, "[^a-zA-Z0-9]", " ")

With this, “ask” AHK to remove all characters from the ActiveWindow variable that don’t match what’s in the brackets:

  • Lowercase
  • Uppercase letter
  • Numbers

Then assign the result to the variable LogWindow.

Clean up the active window's title with RegEx
Clean up the active window’s title with RegEx

With all variables set and all valuable data collected, you are now ready to format the log file and its contents.

LogFilename = %LogFilename%_AppLog.md
LogFile = %LogPath%%LogFilename%

Previously, we assigned the current date to the variable LogFilename. Therefore, for the first line, add “_AppLog.md” on the date to use it as the filename.

Set log file name
Set log file name

In the second line, combine the variable LogPath, specified at the beginning as the destination for the log file associated with the filename. Their combination is the full path name of the log file, assigned to the variable LogFile.

Let’s assign the equivalent value of “empty line, Time – Window’s Name, two more empty lines, a divider, and another empty line, for good measure” for variable FileContent.

FileContent = `n%LogTime% - %LogWindow%`n`n- - -`n
  • Letter “n” asks AHK to enter a new line (equivalent to pressing Enter once).
  • The three dashes will appear as a separator when displayed in a down-compatible viewer.
  • “% LogTime%” and “% LogWindow%” are variables that store the name of the active window and the time it was detected.
Determine the contents of the log file
Determine the contents of the log file

5. Update files

You have specified what we want to write to the file, as well as its path and filename. All that remains is the actual text, as simple as this:

FileAppend, %FileContent%, %LogFile%

Concatenate everything in the variable “FileContent” to file “LogFile”.

Use AHK's Append function to update the log file or create one from scratch
Use AHK’s Append function to update the log file or create one from scratch

The “append” function will add “FileContent” to the file if it exists, but will also create it from scratch if the file doesn’t exist.

There is one final tweak: replace the contents of the variable LastActiveWindow with the currently active window.

Insert title of current active window into LastActiveWindow variable for future checking
Insert title of current active window into LastActiveWindow variable for future checking

To do this, the script should be able to detect the next window change.

LastActiveWindow = %ActiveWindow%

And with that last addition, the window logger is ready! Save the script and run it. Then check the markdown file, it will appear in the script files folder after 10 seconds.

The windows log file is created in the same directory as the script
The windows log file is created in the same directory as the script

Own your own time

You can open the log file with any text editor. However, it will look better if you open in a markdown compatible editor. In the screenshot you can see the log in the popular Typora editor.

The markdown file generated by the script loaded in Typora
The markdown file generated by the script loaded in Typora

It’s an easy way to check which apps you’ve been using the most time in, and it just needs a tool like Notepad to use.

If you want something “more special”, you can always “stylize” the logger output to generate a CSV file instead. As easy as adjusting the variable FileContent and the extension of the created file. You can then import such files into applications like Excel, Google Calc or even third-party time trackers.

Complete script

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
; Variables
; ---------
AppLoggingRate = 10 ; Time interval (in seconds) between active window title captures.
SleepTime := AppLoggingRate * 1000
LogPath = %A_ScriptDir%
LastActiveWindow = 
; Logic
; -----
Loop
{
	Sleep %SleepTime%
	
	WinGetActiveTitle, ActiveWindow
	StoreActiveWindow = %ActiveWindow%
	
	If ActiveWindow != %LastActiveWindow%
	{
		FormatTime, LogTime,, HH:mm:ss
		FormatTime, LogFilename, , yyyy-MM-dd
		
		LogWindow := Regexreplace(ActiveWindow, "[^a-zA-Z0-9]", " ")
		
		LogFilename = %LogFilename%_AppLog.md
		LogFile = %LogPath%%LogFilename%
		
		FileContent = `n%LogTime% - %LogWindow%`n`n- - -`n
		
		sleep 50
		
		FileAppend, %FileContent%, %LogFile%
		LastActiveWindow = %ActiveWindow%
	}
}
Exit

.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *