Scripts

Related topics:

Table of Contents

Introduction

Each script is a plain text file containing lines to be executed by the program (AutoHotkey.exe). A script may also contain hotkeys and hotstrings, or even consist entirely of them. However, in the absence of hotkeys and hotstrings, a script will perform its functions sequentially from top to bottom the moment it is launched.

The program loads the script into memory line by line, and each line may be up to 16,383 characters long. During loading, the script is optimized and validated. Any syntax errors will be displayed, and they must be corrected before the script can run.

The Top of the Script (the Auto-execute Section)

After the script has been loaded, it begins executing at the top line, continuing until a Return, Exit, hotkey/hotstring label, or the physical end of the script is encountered (whichever comes first). This top portion of the script is referred to as the auto-execute section.

Note: While the script's first hotkey/hotstring label has the same effect as return, other hotkeys and labels do not.

A script that lacks hotkeys, hotstrings, visible GUIs, active message monitors, active timers, active OnClipboardChange callback functions, custom tray menu items and the #Persistent directive will terminate after the auto-execute section has completed. Otherwise, it will stay running in an idle state, responding to events such as hotkeys, hotstrings, GUI events, custom menu items, and timers. If these conditions change after the auto-execute section completes (for example, the last timer is disabled), the script may exit when the last running thread completes or the last GUI closes.

Every thread launched by a hotkey, hotstring, menu item, GUI event, or timer starts off fresh with the default values for the following attributes as set in the auto-execute section. If unset, the standard defaults will apply (as documented on each of the following pages): DetectHiddenWindows, DetectHiddenText, SetTitleMatchMode, SendMode, SetKeyDelay, SetMouseDelay, SetWinDelay, SetControlDelay, SetDefaultMouseSpeed, CoordMode, SetStoreCapsLockMode, StringCaseSense, Thread, and Critical.

If the auto-execute section takes a long time to complete (or never completes), the default values for the above settings will be put into effect after 100 milliseconds. When the auto-execute section finally completes (if ever), the defaults are updated again to be those that were in effect at the end of the auto-execute section. Thus, it's usually best to make any desired changes to the defaults at the top of scripts that contain hotkeys, hotstrings, timers, or custom menu items. Also note that each thread retains its own collection of the above settings. Changes made to those settings will not affect other threads.

Excluding whitespace, /* must appear at the start of the line, while */ can appear only at the start or end of a line. It is also valid to omit */, in which case the remainder of the file is commented out.

Splitting a Long Line into a Series of Shorter Ones

Long lines can be divided up into a collection of smaller ones to improve readability and maintainability. This does not reduce the script's execution speed because such lines are merged in memory the moment the script launches.

There are three methods, and they can generally be used in combination:

Continuation prefix: A line that starts with a comma or any other expression operator (except ++ and --) is automatically merged with the line directly above it. In the following example, the second line is appended to the first because it begins with a comma:

FileAppend "This is the text to append.`n"   ; A comment is allowed here.
    , A_ProgramFiles "\SomeApplication\LogFile.txt"  ; Comment.

Similarly, the following lines would get merged into a single line because the last two start with "and" or "or":

if (Color = "Red" or Color = "Green"  or Color = "Blue"   ; Comment.
    or Color = "Black" or Color = "Gray" or Color = "White")   ; Comment.
    and ProductIsAvailableInColor(Product, Color)   ; Comment.

The ternary operator is also a good candidate:

ProductIsAvailable := (Color = "Red")
    ? false  ; We don't have any red products, so don't bother calling the function.
    : ProductIsAvailableInColor(Product, Color)

Although the indentation used in the examples above is optional, it might improve clarity by indicating which lines belong to ones above them. Also, it is not necessary to include extra spaces for lines starting with the words "AND" and "OR"; the program does this automatically. Finally, blank lines or comments may be added between or at the end of any of the lines in the above examples.

Continuation by enclosure: If a line contains an expression or function/property definition with an unclosed (/[/{, it is joined with subsequent lines until the number of opening and closing symbols balances out. In other words, a sub-expression enclosed in parentheses, brackets or braces can automatically span multiple lines in most cases. For example:

myarray := [  ; The opening bracket must be on this line.
  "item 1",
  "item 2",
]
MsgBox(
    "The value of item 2 is " myarray[2],
    "Title",
    "ok iconi"
    )

Continuation expressions may contain both types of comments.

Continuation expressions may contain normal continuation sections. Therefore, as with any line containing an expression, if a line begins with a non-escaped open parenthesis ((), it is considered to be the start of a continuation section unless there is a closing parenthesis ()) on the same line.

Quoted strings cannot span multiple lines using this method alone. However, see above.

Brace ({) at the end of a line does not cause continuation if the program determines that it should be interpreted as the beginning of a block (OTB style) rather than the start of an object literal. Specifically (in descending order of precedence):

A brace can be safely used for line continuation with any function call, expression or control flow statement which does not require a body. For example:

myfn() {
    return {
        key: "value"
    }
}

Continuation section: This method should be used to merge a large number of lines or when the lines are not suitable for the other methods. Although this method is especially useful for auto-replace hotstrings, it can also be used with any expression. For example:

; EXAMPLE #1:
Var := "
(
Line 1 of the text.
Line 2 of the text. By default, a linefeed (`n) is present between lines.
Additionally, "quote marks" are automatically escaped when appropriate.
)"

; EXAMPLE #2:
FileAppend "
(
A line of text.
By default, the hard carriage return (Enter) between the previous line and this one will be written to the file.
	This line is indented with a tab; by default, that tab will also be written to the file.
)", A_Desktop "\My File.txt"

In the examples above, a series of lines is bounded at the top and bottom by a pair of parentheses. This is known as a continuation section. Notice that any code after the closing parenthesis is also joined with the other lines (without any delimiter), but the opening and closing parentheses are not included.

If the line above the continuation section ends with a name character and the section does not start inside a quoted string, a single space is automatically inserted to separate the name from the contents of the continuation section.

Quote marks are automatically escaped (i.e. they are interpreted as literal characters) if the continuation section starts inside a quoted string, as in the examples above. Otherwise, quote marks act as they do normally; that is, continuation sections can contain expressions with quoted strings.

By default, leading spaces or tabs are omitted based on the indentation of the first line inside the continuation section. If the first line mixes spaces and tabs, only the first type of character is treated as indentation. If any line is indented less than the first line or with the wrong characters, all leading whitespace on that line is left as is.

The default behavior of a continuation section can be overridden by including one or more of the following options to the right of the section's opening parenthesis. If more than one option is present, separate each one from the previous with a space. For example: ( LTrim Join|.

Join: Specifies how lines should be connected together. If this option is omitted, each line except the last will be followed by a linefeed character (`n). If the word Join is specified by itself, lines are connected directly to each other without any characters in between. Otherwise, the word Join should be followed immediately by as many as 15 characters. For example, Join`s would insert a space after each line except the last ("`s" indicates a literal space -- it is a special escape sequence recognized only by Join). Another example is Join`r`n, which inserts CR+LF between lines. Similarly, Join| inserts a pipe between lines. To have the final line in the section also ended by a join-string, include a blank line immediately above the section's closing parenthesis.

Known limitation: If the Join string ends with a colon, it must not be the last option on the line. For example, (Join: is treated as the label "(Join" and (LTrim Join: is unsupported, but (Join: C is okay.

LTrim: Omits all spaces and tabs at the beginning of each line. This is usually unnecessary because of the default "smart" behaviour.

LTrim0 (LTrim followed by a zero): Turns off the omission of spaces and tabs from the beginning of each line.

RTrim0 (RTrim followed by a zero): Turns off the omission of spaces and tabs from the end of each line.

Comments (or Comment or Com or C): Allows semicolon comments inside the continuation section (but not /*..*/). Such comments (along with any spaces and tabs to their left) are entirely omitted from the joined result rather than being treated as literal text. Each comment can appear to the right of a line or on a new line by itself.

` (accent): Treats each backtick character literally rather than as an escape character. This also prevents the translation of any explicitly specified escape sequences such as `r and `t.

): If a closing parenthesis appears in the continuation section's options (except as a parameter of the Join option), the line is reinterpreted as an expression instead of the beginning of a continuation section. This allows expressions like (x.y)[z]() to work without the need to escape the opening parenthesis.

Escape sequences such as `n (linefeed) and `t (tab) are supported inside the continuation section except when the accent (`) option has been specified.

When the comment option is absent, semicolon and /*..*/ comments are not supported within the interior of a continuation section because they are seen as literal text. However, comments can be included on the bottom and top lines of the section. For example:

FileAppend "   ; Comment.
; Comment.
( LTrim Join    ; Comment.
     ; This is not a comment; it is literal. Include the word Comments in the line above to make it a comment.
)", "C:\File.txt"   ; Comment.

As a consequence of the above, semicolons never need to be escaped within a continuation section.

A continuation section cannot produce a line whose total length is greater than 16,383 characters (if it tries, the program will alert you the moment the script is launched). One way to work around this is to do a series of concatenations into a variable. For example:

Var := "
(
...
)"
Var .= "`n  ; Add more text to the variable via another continuation section.
(
...
)"
FileAppend Var, "C:\My File.txt"

Since a closing parenthesis indicates the end of a continuation section, to have a line start with literal closing parenthesis, precede it with an accent/backtick: `). However, this cannot be combined with the accent (`) option.

A continuation section can be immediately followed by a line containing the open-parenthesis of another continuation section. This allows the options mentioned above to be varied during the course of building a single line.

The piecemeal construction of a continuation section by means of #Include is not supported.

Convert a Script to an EXE (ahk2exe)

A script compiler (courtesy of fincs) is included with the program.

Once a script is compiled, it becomes a standalone executable; that is, AutoHotkey.exe is not required in order to run the script. The compilation process creates an executable file which contains the following: the AutoHotkey interpreter, the script, any files it includes, and any files it has incorporated via the FileInstall function.

Ahk2Exe can be used in the following ways:

  1. GUI Interface: Run the "Convert .ahk to .exe" item in the Start Menu.
  2. Right-click: Within an open Explorer window, you can right-click any .ahk file and select "Compile Script" (only available if the script compiler option was chosen when AutoHotkey was installed). This creates an EXE file of the same base filename as the script, which appears after a short time in the same directory. Note: The EXE file is produced using the same custom icon, .bin file and use MPRESS setting that were last used by Method #1 above.
  3. Command Line: The compiler can be run from the command line with the following parameters:
    Ahk2Exe.exe /in MyScript.ahk [/out MyScript.exe] [/icon MyIcon.ico] [/bin AutoHotkeySC.bin] [/mpress 0or1]
    For example:
    Ahk2Exe.exe /in "MyScript.ahk" /icon "MyIcon.ico"
    Usage:

Notes:

The compiler's source code and newer versions can be found at GitHub.

Compressing Compiled Scripts

Ahk2Exe optionally uses MPRESS (a freeware program by MATCODE Software) to compress compiled scripts. If mpress.exe is present in the "Compiler" subfolder where AutoHotkey was installed, it is used automatically unless it is disabled via /mpress 0 or the GUI setting.

Official website (was offline in March 2016): http://www.matcode.com/mpress.htm

Mirror (downloads and information): https://autohotkey.com/mpress/

Note: While compressing the script executable prevents casual inspection of the script's source code using a plain text editor like Notepad or a PE resource editor, it does not prevent the source code from being extracted by tools dedicated to that purpose.

Passing Command Line Parameters to a Script

Scripts support command line parameters. The format is:

AutoHotkey.exe [Switches] [Script Filename] [Script Parameters]

And for compiled scripts, the format is:

CompiledScript.exe [Switches] [Script Parameters]

Switches: Zero or more of the following:

SwitchMeaningWorks compiled?
/f or /force Launch unconditionally, skipping any warning dialogs. This has the same effect as #SingleInstance Off. Yes
/r or /restart Indicate that the script is being restarted (this is also used by the Reload function, internally). Yes
/ErrorStdOut Send syntax errors that prevent a script from launching to stderr rather than displaying a dialog. See #ErrorStdOut for details. This can be combined with /iLib to validate the script without running it. Yes
/Debug Connect to a debugging client. For more details, see Interactive Debugging. No
/CPn Overrides the default codepage used to read script files. For more details, see Script File Codepage. No
/iLib "OutFile"

AutoHotkey loads the script but does not run it. For each script file which is auto-included via the library mechanism, two lines are written to the file specified by OutFile. These lines are written in the following format, where LibDir is the full path of the Lib folder and LibFile is the filename of the library:

#Include LibDir\
#IncludeAgain LibDir\LibFile.ahk

If the output file exists, it is overwritten. OutFile can be * to write the output to stdout.

If the script contains syntax errors, the output file may be empty. The process exit code can be used to detect this condition; if there is a syntax error, the exit code is 2. The /ErrorStdOut switch can be used to suppress or capture the error message.

No

Script Filename: This can be omitted if there are no Script Parameters. If omitted (such as if you run AutoHotkey directly from the Start menu), the program looks for a script file called AutoHotkey.ahk in the following locations, in this order:

The filename AutoHotkey.ahk depends on the name of the executable used to run the script. For example, if you rename AutoHotkey.exe to MyScript.exe, it will attempt to find MyScript.ahk. If you run AutoHotkeyU32.exe without parameters, it will look for AutoHotkeyU32.ahk.

Specify an asterisk (*) for the filename to read the script text from standard input (stdin). For an example, see ExecScript().

Script Parameters: The string(s) you want to pass into the script, with each separated from the next by a space. Any parameter that contains spaces should be enclosed in quotation marks. A literal quotation mark may be passed in by preceding it with a backslash (\"). Consequently, any trailing slash in a quoted parameter (such as "C:\My Documents\") is treated as a literal quotation mark (that is, the script would receive the string C:\My Documents"). To remove such quotes, use A_Args[1] := StrReplace(A_Args[1], '"')

Incoming parameters, if present, are stored as an array in the built-in variable A_Args, and can be accessed using array syntax. A_Args[1] contains the first parameter. The following example exits the script when too few parameters are passed to it:

if A_Args.Length() < 3
{
    MsgBox "This script requires at least 3 parameters but it only received " A_Args.Length() "."
    ExitApp
}

If the number of parameters passed into a script varies (perhaps due to the user dragging and dropping a set of files onto a script), the following example can be used to extract them one by one:

for n, param in A_Args  ; For each parameter:
{
    MsgBox "Parameter number " n " is " param "."
}

If the parameters are file names, the following example can be used to convert them to their case-corrected long names (as stored in the file system), including complete/absolute path:

for n, GivenPath in A_Args  ; For each parameter (or file dropped onto a script):
{
    Loop Files, GivenPath, "FD"  ; Include files and directories.
        LongPath := A_LoopFileFullPath
    MsgBox "The case-corrected long path name of file`n" GivenPath "`nis:`n" LongPath
}

Script File Codepage

The characters a script file may contain are restricted by the codepage used to load the file.

Note that this applies only to script files loaded by AutoHotkey, not to file I/O within the script itself. FileEncoding controls the default encoding of files read or written by the script, while IniRead and IniWrite always deal in UTF-16 or ANSI.

As all text is converted (where necessary) to the native string format, characters which are invalid or don't exist in the native codepage are replaced with a placeholder: '�'. This should only occur if there are encoding errors in the script file or the codepages used to save and load the file don't match.

RegWrite may be used to set the default for scripts launched from Explorer (e.g. by double-clicking a file):

; Uncomment the appropriate line below or leave them all commented to
;   reset to the default of the current build.  Modify as necessary:
; codepage := 0        ; System default ANSI codepage
; codepage := 65001    ; UTF-8
; codepage := 1200     ; UTF-16
; codepage := 1252     ; ANSI Latin 1; Western European (Windows)
if (codepage != "")
    codepage := " /CP" . codepage
cmd := Format('"{1}"{2} "%1" %*', A_AhkPath, codepage)
key := "AutoHotkeyScript\Shell\Open\Command"
if A_IsAdmin    ; Set for all users.
    RegWrite cmd, "REG_SZ", "HKCR\" key
else            ; Set for current user only.
    RegWrite cmd, "REG_SZ", "HKCU\Software\Classes\" key

This assumes AutoHotkey has already been installed. Results may be less than ideal if it has not.

Debugging a Script

Built-in functions such as ListVars and Pause can help you debug a script. For example, the following two lines, when temporarily inserted at carefully chosen positions, create "break points" in the script:

ListVars
Pause

When the script encounters these two lines, it will display the current contents of all variables for your inspection. When you're ready to resume, un-pause the script via the File or Tray menu. The script will then continue until reaching the next "break point" (if any).

It is generally best to insert these "break points" at positions where the active window does not matter to the script, such as immediately before a WinActivate function. This allows the script to properly resume operation when you un-pause it.

The following functions are also useful for debugging: ListLines, KeyHistory, and OutputDebug.

Some common errors, such as typos and missing "global" declarations, can be detected by enabling warnings.

Interactive Debugging

Interactive debugging is possible with a supported DBGp client. Typically the following actions are possible:

Note that this functionality is disabled for compiled scripts.

To enable interactive debugging, first launch a supported debugger client then launch the script with the /Debug command-line switch.

AutoHotkey.exe /Debug[=SERVER:PORT] ...

SERVER and PORT may be omitted. For example, the following are equivalent:

AutoHotkey /Debug "myscript.ahk"
AutoHotkey /Debug=localhost:9000 "myscript.ahk"

To attach the debugger to a script which is already running, send it a message as shown below:

ScriptPath := "" ; SET THIS TO THE FULL PATH OF THE SCRIPT
A_DetectHiddenWindows := true
if WinExist(ScriptPath " ahk_class AutoHotkey")
    ; Optional parameters:
    ;   wParam  = the IPv4 address of the debugger client, as a 32-bit integer.
    ;   lParam  = the port which the debugger client is listening on.
    PostMessage DllCall("RegisterWindowMessage",  Str, "AHK_ATTACH_DEBUGGER")

Once the debugger client is connected, it may detach without terminating the script by sending the "detach" DBGp command.

Script Showcase

See this page for some useful scripts.