Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
313 lines (228 sloc) 11.7 KB
layout author title date desc bigimg img categories tags extras interesting toc todo
Wouter Van Schandevijl
Autohotkey Debugging
How to speed up and perhaps also help you get out of a pinch while debugging your Authotkey scripts...
url desc origin
Photo by Jason D
url desc origin title linkUrl
Is that even Authotkey code?? Are you kidding me???
Photo by Taras Shypka
git desc
A curated list of awesome
git desc
Mi-Ke contains most stuff in this blog post, and then some.
title icon
🐛 To The Trenches
Setting the default editor for "Edit This Script" tray menu item
Interactive debugging?

If you are like me, you just started writing Authotkey scripts without ever really taking the time to learn the language properly. This blog post contains some scripts and tools to help you try make some sense of what is going on.


{% include github-stars.html url="Uberi/Yunit" desc="Nothing beats a test runner: Uberi and infogulch created one." %}

Our fork of the super simple Yunit Autohotkey testing framework adds a ps1 colored console runner and monitoring. Check our Github README for a screenshot and code example.

Builtin functionality


MsgBox pauses the current thread so you can use "other debugging tools" while displaying something.

var := 10
vas := 5
MsgBox aaargh %var%
MsgBox % var "and" vas


Tooltip creates a non-blocking, always-on-top window anywhere on the screen.

Tooltip [, Text`nMoreText, X, Y, WhichTooltip]
  • If Text is omitted, the tooltip is hidden.
  • If X & Y are omitted, the tooltip is displayed near the mouse cursor.
  • X & Y are relative to the active window. Use CoordMode to display somewhere else.
  • WhichTooltip: A number between 1-20 to control multiple tooltips.


I'll be honest, they are not the prettiest tools in the shed. They do come in handy from time to time and are available from the default tray icon menu.

  • KeyHistory: Unsure how to bind a certain key/mouse button? Use this tool!
  • ListVars: Lists all variable names with content. Good for primitives (ie: an Array displays Object object {address: 0x5B2AD0}).
  • ListLines: Script lines most recently executed.
  • ListHotkeys: Very crude listing of all registered hotkeys.

Scripts to retrieve and parse the output for these windows.

Window Spy

Activate scripts only in certain contexts with IfWinActive. But how to determine this ahk_class thingy?

; Esc twice to open/close DevTools... But only in Chrome
#IfWinActive, ahk_class Chrome_WidgetWin
If (A_PriorHotKey = A_ThisHotKey and A_TimeSincePriorHotkey < 500)
    Send {F12}

To figure that out (and much more!), bundled with Autohotkey comes the immensely useful utility Window Spy (usually called AU3_Spy.exe). It's also available from the tray menu.


; Default: Disable all warnings.
#Warn All, Off

; Every warning in a MsgBox.

; Warn when a local variable is used before it's set in OutputDebug.
#Warn UseUnsetLocal, OutputDebug

Warning Types:

  • UseUnsetLocal and UseUnsetGlobal
  • LocalSameAsGlobal
  • ClassOverwrite
  • UseEnv: Warn when a variable used has the same name as an environment variable. To avoid this confusion, start with #NoEnv and use EnvGet / EnvSet for interacting with environment variables instead.


OutputDebug, Value of %var%

If the script's process has no debugger, the system debugger displays the string. Follow OutputDebug with, for example DebugView (Dbgview.exe) from Sysinternals.



Pause will toggle the current thread. Hotstrings and Hotkeys will still run. A_IsPaused contains the pause state of the underlying thread.

; Freezes the current thread with Windows + Pause
#Pause::Pause, On
; Also: Off and Toggle (default)


Suspend will enable/disable all hotkeys and hotstrings. A_IsSuspended contains the script suspension state.

; Suspend, On/Off/Toggle (default)
MsgBox % "Hotkeys & hotstrings are now " (A_IsSuspended ? "disabled" : "enabled")

Suspend, Permit
MsgBox I will run even when the script is suspended

By default the script can also be paused/suspended via it's tray icon menu and a different tray icon is shown when toggled. Nothing is worse as you thinking your code doesn't work as expected when it's not even running :)

Exit & ExitApp

The #Persistent directive will make a script not directly Exit after the auto-execute section. Exit merely exits the current thread. Use ExitApp to close the script completely.

A script is automatically persistent when:

  • It has defined hotkeys or hotstrings
  • It sets NumLock, ScrollLock or CapsLock AlwaysOn or AlwaysOff

Use #Persistent when you do not have any of the above but you do have timers or custom menu items.

; Control + Win + Alt + Pause: Emergency exit
Suspend, Permit

; Can register multiple OnExit

ExitFunc(ExitReason, ExitCode)
  if ExitReason not in Logoff,Shutdown
    MsgBox, 4, , Are you sure you want to exit?
    IfMsgBox, No
      return 1  ; Return non-zero to prevent exit.


  • Logoff: User logs off
  • Shutdown: Computer shuts down (detect and abort a shutdown with OnMessage(0x11, "WM_QUERYENDSESSION"))
  • Close: A WM_CLOSE or WM_QUIT message
  • Error
  • Menu: From the tray icon menu
  • Commands: Exit, ExitApp, Reload and #SingleInstance

Custom Scripts

Autoreload on save

Reload the Autohotkey script on save when working on it in your favourite editor.

; Trigger on Control + S
; ~ = Also execute native function
; Run even when script is suspended
Suspend, Permit

; Only in Sublime Text and Visual Studio Code
if (!WinActive("ahk_class PX_WINDOW_CLASS") and !WinActive("ahk_exe Code.exe"))

; Only when the script dir/filename is in the titlebar
WinGetActiveTitle, winTitle
if (InStr(winTitle, A_Scriptdir) or InStr(winTitle, A_ScriptName))

; Only when the top dir name is in the titlebar
SplitPath, A_Scriptdir, topDir
if (InStr(winTitle, topDir))



Should your IntelliSense not cut it, open the online docs on the selected Autohotkey keyword with Capslock + A. If it doesn't match a keyword, google "Autohotkey selected text".

Capslock & A::
; Get the currently selected text
; (with some clipboard juggling:)
old := clipboard
clipboard =
Send, ^c
ClipWait, 3
needle := clipboard
clipboard := old

ahkCommands =
  Break,Catch,Click,ClipWait,Continue,Control,ControlClick,ControlFocus,ControlGet,ControlGetFocus, ControlGetPos,ControlGetText,ControlMove, ControlSend,ControlSendRaw,ControlSetText,CoordMode,Critical, DetectHiddenText,Drive,DriveGet,DriveSpaceFree,Edit,Else,EnvAdd,EnvDiv,EnvGet, EnvMult,EnvSet,EnvSub, EnvUpdate,Exit,ExitApp,FileAppend,FileCopy,FileCopyDir,FileCreateDir,FileCreateShortcut,FileDelete, FileInstall,FileGetAttrib, FileGetShortcut,FileGetSize,fileGetVersion,FileMove,FileMoveDir,FileOpen, FileRead,FileReadLine,FileRecycle,FileRecycleEmpty,FileRemoveDir, FileSelectFile,FileSelectFolder, FileSetAttrib,FileSetTime,Finally,For,Format,FormatTime,GetKeyState,Gosub,Goto,GroupActive,GroupAdd, GroupClose,GroupDeactivate,Gui,GuiControl,GuiControlGet,Hotkey,if,IfEqual,IfNotEqual,IfExist,IfNotExist, IfGreater,IfGreaterOrEqual,IfInString, IfNotInString,IfLess,IfLessOrEqual,IfMsgBox,IfWinActive,IfWinNotActive, IfWinExist,IfWinNotExist,ImageSearch,IniDelete,IniRead,IniWrite,Input, InputBox,KeyHistory,KeyWait,ListHotkeys, ListLines,ListVars,Loop,Menu,MenuGetHandle,MenuGetName,MouseClick,MouseClickDrag,MouseGetPos,MouseMove,MsgBox, OnExit,OutputDebug,Pause,PixelGetColor,PixelSearch,PostMessage,Process,Progress,Random,RegDelete,RegRead,RegWrite, Reload,Return,Run,RunAs,RunWait,Send,SendRaw,SendInput,SendPlay,SendEvent,SendLevel,SendMessage,SendMode, SetBatchLines,SetCapsLockState,SetControlDelay,SetDefaultMouseSpeed,SetEnv,SetFormat,SetKeyDelay,SetMouseDelay, SetNumLockState,SetScrollLockState,SetregView,SetStoreCapsLockMode,SetTimer,SetTitleMatchMode,SetWinDelay, SetWorkingDir,Shutdown,Sleep,Sort,SoundBeep,SoundGet,SoundGetWaveVolume,SoundPlay,SoundSet,SoundSetWaveVolume, SplashImage,SplashTextOn,SplashTextOff,SplitPath,StatusBarGetText,StatusBarWait,StringCaseSense,StringLeft, StringRight,StringLower,StringReplace,StringSplit,StringTrimLeft,StringTrimRight,StringUpper,Suspend,SysGet, Thread,Throw,ToolTip,Transform,TrayTip,Until,UrlDownloadToFile,While,WinActivate,WinActivateBottom,WinClose, WinGetActiveStats,WinGetActiveTitle,WinGetClass,WinGet,WinGetPos,WinGetText,WinGetTitle,WinHide,WinKill,WinMaximize, WinMenuSelectItem,WinMinimize,WinMinimizeAll,WinMinimizeAllUndo,WinMove,WinRestore,WinSet,WinSetTitle,WinShow, WinWait,WinWaitActive,WinWaitClose,WinWaitNotActive,ClipboardTimeout,CommentFlag,Delimiter,DerefChar,ErrorStdOut, EscapeChar,HotkeyInterval,HotkeyModifierTimeout,Hotstring,Include,IncludeAgain,InputLevel,InstallKeybdHook, InstallMouseHook,LTrim,MaxHotkeysPerInterval,MaxMem,MaxThreads,MaxThreadsBuffer,MaxThreadsPerHotkey, MenuMaskKey,NoEnv,NoTrayIcon,Persistent,SingleInstance,UseHook,Warn,WinActivateForce

if (IsFunc(needle) or InStr(ahkCommands, needle)) {
} else {

Script to open Autohotkey.chm instead.


A_ScriptHwnd contains the unique ID (HWND) of the script's hidden main window.

You can’t perform that action at this time.