Automating tasks with AutoIt

Introduction

AutoIt is a freeware alternative to applications like AutoHotKey to automate tasks through hotkeys/hotstrings and drive GUI applications. It used to be open-source — AutoHotKey was forked from AutoIt around 2005 —, but was closed-source later after a family feud. AHK is updated more frequently than AutoIt.

AutoIt is a procedural language and its syntax looks like BASIC, while AHK is a mix between C and Pascal. Although it has nowhere near the breadth of eg. Python, AutoIt could be good enough and used as an alternative to (Power|Pure|Free)Basic to write CLI/GUI apps.

In addition to native features, AutoIt is enhanced through User Defined Functions (UDFs), which are themselves coded in AutoIt and thus also have the .au3 extension. Some of them are included in the AutoIt installer, while others must be downloaded and installed manually — preferably in the User Include Folder as set through Tools > SciTE Config/CTRL+1. As AutoIt ships with a modified version of SciTE, it's not a good idea to manually upgrade it. If you still want to run a more recent version, check the thread.

Since AutoIt is primarily meant to automate the use of GUI apps, one of the important UDFs is IUIAutomation, which is the AutoIt implementation of Microsoft's UI Automation; It provides more ways to interact with GUI widgets.

Learning AutoIt

In addition to the AutoIt.chm help file — which is the offline version of the online doco —, the wiki, the forum, and the source code examples in \AutoIt3\Examples, information can also be found in the following:

There are no more recent books to learn (but then, AutoIt isn't updated very frequently), and the help file is mostly a reference manual not a tutorial, although each function does include one or more examples.

A possible plan to learn AutoIt:

  1. Download and install the AutoIt full package, launch the SciTEAutoIt editor, and run "Hello, World!"
  2. Core Language: Variables, conditional statements, loops, functions, string manipulation, arrays, files and directories
  3. Hotkeys
  4. Automating GUI apps
  5. Automating CLI apps (RunWait(), Std*(), etc.)
  6. UDFs
  7. Writing GUI apps

Getting Started

As of version 3.3.6.1, AutoIt consists in the following programs:

To install UDFs, if you're using SciTE4AutoIt3, it's better to create a new directory outside the AutoIt folder so that the files aren't affected when upgrading AutoIt. To tell SciTE to find those files, use Tools > SciTE Config, and fill the "User Include Folders" in the "General 1" tab.

Working with windows (automating)

AutoIt's original raison d'être.

To find information about a window

Use install\Au3Info.exe.

Check UIASpy - UI Automation Spy Tool

To find a window

There are two parts: Its Title, and "Text" which can be any text found in the window (buttons, textboxes, etc.)

WinWaitActive("Untitled - Notepad", "This is some text!")

Timeout can be increased thusly:

Opt("WinWaitDelay", 1)

To find a window with just part of title/text

Opt("WinTitleMatchMode", 1) ;1=start (default), 2=subStr, 3=exact, 4=advanced (deprecated), -1 to -4=Nocase

Note: Opt() = AutoItSetOption()

More information here.

WinExists, WinActive, WinWait, WinWaitActive, WinActivate, _WinWaitActivate?

Const $MyWindow="My window"
WinActivate ($MyWindow)
if WinWaitActive($MyWindow, "", 5) = False Then
    MsgBox($MB_SYSTEMMODAL, "Failed finding window", "Bad")
Else
    ;Do something
EndIf

https://www.autoitscript.com/autoit3/docs/functions/WinExists.htm

https://www.autoitscript.com/autoit3/docs/functions/WinWait.htm

https://www.autoitscript.com/autoit3/docs/functions/WinActive.htm

https://www.autoitscript.com/autoit3/docs/functions/WinActivate.htm

https://www.autoitscript.com/autoit3/docs/functions/WinWaitActive.htm

_WinWaitActivate() is not a native function: It is generated by the Au3Record.exe application, which no longer ships with AutoIt "from v3.3.14.1 as it triggers many AV false positives".

Func _WinWaitActivate($title,$text,$timeout=0)
        Local $result = False
        $result = WinWait($title,$text,$timeout)
        if $result = False Then Exit MsgBox($MB_ICONERROR,"Bad...","Window not displayed")
 
        If Not WinActive($title,$text) Then WinActivate($title,$text)
        WinWaitActive($title,$text,$timeout)
EndFunc

To record an action

Launch \Extras\Au3Record\Au3Record.exe to record an action that Au3Record will then save as source code that you can use in your scripts.

Caution: Code generated Au3Record isn't always reliable, some functions won't work. YMMV.

Note: _WinWaitActivate() is not part of AutoIt; Its code found below must be included in the script.

Note: "AutoIt Recorder utility is not available from AutoIt Version 3.3.14.1." (source)

To use control/arrow keys

;CTRL+A

Send("^a")

Sleep(3000)

;CTRL+C

Send("^c")

;CTRL+V

Send("^v")

;jump to first line in text

Send("^{HOME}")

Accessing a control/widget

ControlSend("Untitled - Notepad", "", "Edit1", "This is some text")

ControlClick("My Window", "", "[ID:254]")

To send keys to window/control

http://www.autoitscript.com/autoit3/docs/functions/ControlClick.htm

http://www.autoitscript.com/autoit3/docs/functions/ControlCommand.htm

http://www.autoitscript.com/autoit3/docs/functions/ControlSend.htm

http://www.autoitscript.com/autoit3/docs/functions/ControlFocus.htm

(only as last resort)

http://www.autoitscript.com/autoit3/docs/functions/Send.htm

http://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm

How to interact with controls

Besides the Control*() functions, there are also: StatusbarGetText, WinActivate, WinGetClassList, WinMenuSelectItem.

ControlSend("Untitled - Notepad", "", "[CLASSNN:Edit1]", "This is some text")

ControlSetText("My Window", "", "[NAME:textBoxFolder]", "C:\Some\Folder")

ControlClick("My Window", "", "[ID:254]")

ControlClick("My Window", "", "[CLASS:Button; TEXT:Finish; INSTANCE:2]")

Note: ControlSetText() sometimes doesn't work as expected; If that case, try ControlSend() instead.

Sample code

Hello, world!

#include <MsgBoxConstants.au3>
 
MsgBox($MB_OK, "Tutorial", "Hello World!")

The EXE is about 1MB, and its size can be halved further through UPX.

Prompting for a string

#include <StringConstants.au3>

Local $sAnswer = InputBox("Type anything", "My text")

if not $sAnswer Then Exit ConsoleWrite("Closed inputbox" & @CRLF)

$sAnswer = StringStripWS($sAnswer,$STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES)

;Two items expected

If $aArray[0] <> 2 Then Exit ConsoleWrite("Expected two items, got " & UBound($aArray)& @CRLF)

Local $item1 = $aArray[1]

Local $item2 = $aArray[2]

Prompting for a directory

Local $sFileSelectFolder = FileSelectFolder("Select a folder", "")

If @error Then Exit ConsoleWrite("Closed directory dialog" & @CRLF)

Prompting for files

#include <File.au3>

$aArray = _FileListToArrayRec($sFileSelectFolder, "*.jpg", $FLTAR_FILES , $FLTAR_RECUR, $FLTAR_NOSORT,$FLTAR_FULLPATH  )

If UBound($aArray) = 0 Then Exit ConsoleWrite("zero elements") ;1D array only

Showing the current line in the script

ConsoleWrite(@ScriptLineNumber & @CRLF)

Variables and constants

Variables are stored as variants, must start with the $ character and may only contain letters, numbers and the underscore _ character. Note that all variable names are case insensitive: MyVariable() is the same as MyvARiAblE(). Variables are declared and created with the Local and Global keywords - Dim can also be used, although this is not recommended. Although all variables outside functions are automatically Global, and all variables inside functions are Local, it's good practice to use the right keyword.

Constants are declared and created using Const keyword and must be initialised with a value.

To refer to macros such as environment variables: @ComputerName

Although not required, it's best practise to start a user defined function name with the underscore “_†to differentiate it from prebuilt functions, eg. _myFunction().

It's a good idea to use "Opt('MustDeclareVars', 1)" to make sure variables are always declared. Or even better: Use the following type of command to tell AutoItWrapper to call Au3Check.exe:

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 3 -w 4 -w 5 -w 6

To edit a script

Launch the SciTE editor in install\SciTe\SciTE.exe

To clear the console window in SciTE, use SHIFT+F5. To check a script's syntax without running it, use CTRL+F5.

To comment a line

Use ";"

To comment a block of text

SciTE/AutoIt provides three options to comment a block of lines; Only the first option provides a way to uncomment

In addition, AutoIt provides a fourth way to comment a block of text:

#comments-start
…
#comments-end

To read the command-line input parameters

MsgBox($MB_OK, "Passed Parameters", $CmdLine[0] & " parameters have been passed to this script:")

For $i = 1 To $CmdLine[0]

    MsgBox($MB_OK, "Passed Parameters", "Parameter " & $i & ": " & $CmdLine[$i])

Next

;Get input file

If $CmdLine[0] == 1 and $CmdLine[1] and FileExists($CmdLine[1]) Then

        $INPUTFILE = $CmdLine[1]

EndIf

To prevent the user from disturbing the script

; Disable user input from the mouse and keyboard.

BlockInput($BI_DISABLE)

; Blah

BlockInput($BI_ENABLE)

To split a long string

"my "  & _

"long string"

Trimming string left and right

#include <StringConstants.au3>

;to remove spaces within, add + $STR_STRIPSPACES

Local $sString = StringStripWS("   Blah    ", $STR_STRIPLEADING + $STR_STRIPTRAILING)

MsgBox($MB_SYSTEMMODAL, "", $sString)

Array

The array.au3 UDF offers extended functions to handle arrays, eg. _ArrayDisplay($myarray)

Enum is a way to mimic dictionary arrays:

Local Enum $eTitle, $eIntroText_bb, $eFullText_bb, $eName
ConsoleWrite($aResult[$eTitle])

To set/get clipboard contents

#include <Constants.au3>

#include <MsgBoxConstants.au3>

#include <Date.au3>

#include <Clipboard.au3>

ClipPut(_NowTime())

Local $sClipboard = ClipGet()

MsgBox($MB_SYSTEMMODAL, "Clipboard", $sClipboard)

To send large amounts of text to a text widget

Pasting the clipboard with ClipPut() or send("^v") is much faster than sending text via send().

Since send() is a blocking function, it's not supposed to proceed until it's done sending the text anyway.

For/Next Loop

For $i = 5 To 1 Step -1

    MsgBox($MB_SYSTEMMODAL, "", "Count down!" & @CRLF & $i)

Next

To pause for a few seconds

Sleep(1000) ; sleep for 1s

To move the mouse at the center of the screen

#include <Misc.au3>

CHECK MouseMove(@DesktopWidth/2, @DesktopHeight/2)

Including files

To include files: #include <myfile.au3>

To include an external file into the AutoIt output EXE à la NSIS: FileInstall(Source,Destination[,flag])

Writing to a text file

#include <FileConstants.au3>

$sFileName = @ScriptDir &"\Test.txt"

$hFilehandle = FileOpen($sFileName, $FO_OVERWRITE)

If FileExists($sFileName) Then

    MsgBox($MB_SYSTEMMODAL, "File", "Exists")

Else

    MsgBox($MB_SYSTEMMODAL, "File", "Does not exist")

EndIf

FileWrite($hFilehandle, "This is line 1")

FileFlush($hFilehandle)

MsgBox($MB_SYSTEMMODAL, "File Content", FileRead($sFileName))

FileClose($hFilehandle)

;FileDelete($sFileName)

Exiting

Exit

Exit(1)

Exit(2)

If some_error Then Exit MsgBox($MB_SYSTEMMODAL, "You have an error", "Some text")

StringRegExp(Replace)

A first example:

#include <StringConstants.au3>
 
Local $aResult = StringRegExp("This is a test example", '(te)(st)', $STR_REGEXPARRAYMATCH)
If Not @error Then
        MsgBox($MB_OK, "SRE Example 4 Result", $aResult[0] & "," & $aResult[1])
EndIf

There is apparently no way to configure PCRE externally for the duration of a script, ie. without adding settings to every single pattern.

Note: The PCRE regex engine that AutoIt uses is single-line by default. If you need to find a pattern in a multi-line string, you must tell PCRE explicitely: Prepend (?m) for multi-line:

$array = StringRegExp($data, "(?mi)^(\d+) some text", 3)

Here's how to extract the second part in a two-item string with a TAB delimiter:

$array = StringRegExp("John" & @TAB & "123", "\t(\d+)', 1)
for $i = 0 to UBound($array) - 1
    msgbox(0, "Items found", $array[0])
Next

To find and replace patterns:

Local $sOutput = StringRegExpReplace($sInput, '(\d{2})/(\d{2})/(\d{4})', ' $2.$1.$3 ')

The flag can have five different values:

$STR_REGEXPARRAYMATCH returns an array of matches while $STR_REGEXPARRAYFULLMATCH returns an array of matches including the full match (Perl / PHP style).

$STR_REGEXPARRAYFULLMATCH and $STR_REGEXPARRAYGLOBALFULLMATCH include the full matching text as the first element of the return array, while $STR_REGEXPARRAYMATCH and $STR_REGEXPARRAYGLOBALMATCH only return the captured groups.

$STR_REGEXPARRAYGLOBALMATCH returns an array of global matches while $STR_REGEXPARRAYGLOBALFULLMATCH returns an array of arrays containing global matches including the full match (Perl / PHP style).

Here's how to see what each option does:

Local $aArray = 0
Local $sInput = "/kml/Document/name"
 
$aArray= StringRegExp($sInput, "(.+)\/",$STR_REGEXPARRAYMATCH)
_ArrayDisplay($aArray, "Option $STR_REGEXPARRAYMATCH")
 
$aArray= StringRegExp($sInput, "(.+)\/",$STR_REGEXPARRAYFULLMATCH)
_ArrayDisplay($aArray, "Option $STR_REGEXPARRAYFULLMATCH")
 
$aArray= StringRegExp($sInput, "(.+)\/",$STR_REGEXPARRAYGLOBALMATCH)
_ArrayDisplay($aArray, "Option $STR_REGEXPARRAYGLOBALMATCH")
 
$aArray= StringRegExp($sInput, "(.+)\/",$STR_REGEXPARRAYGLOBALFULLMATCH)
_ArrayDisplay($aArray, "Option $STR_REGEXPARRAYGLOBALFULLMATCH")

As a reference, here's how to perform the same kind of search with string functions:

Local $iPost = StringInStr($sInput, "/",$STR_NOCASESENSE , -1) ;Use a negative occurrence to search from the right side
ConsoleWrite(StringLeft ($sInput, $iPost-1)) ; -1 to ignore trailing /

Generating a random alphanumeric string

Func _MakeString()

    Local $aSplit = StringSplit('abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', '')

    Local $sHoldString = ''

    For $iCC = 1 To Random(10, 15, 1)

        $sHoldString &= $aSplit[Random(1, 62, 1)]

    Next

    Return $sHoldString

EndFunc

Generating a GUID

#include <WinAPICom.au3>

ConsoleWrite(_WinAPI_CreateGUID() & @CRLF)

Calling a function every x ms

AdlibRegister('_UpdateEdit', 1000)
...
Func _UpdateEdit()
    Local $sMoreText =  @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC
    GUICtrlSetData($idEdit, GUICtrlRead($idEdit) & @CRLF & $sMoreText)
    _GUICtrlEdit_Scroll($idEdit, $SB_SCROLLCARET)
EndFunc

Useful constants

#include <AutoItConstants.au3>
#include <ColorConstants.au3>
#include <Constants.au3>
#include <DirConstants.au3>
#include <EditConstants.au3>
#include <FileConstants.au3>
#include <FontConstants.au3>
#include <GUIConstantsEx.au3>
#include <InetConstants.au3>
#include <MsgBoxConstants.au3>
#include <ProcessConstants.au3>
#include <StaticConstants.au3>
#include <StringConstants.au3>
#include <WindowsConstants.au3>

Msgbox Constants (MsgBoxConstants.au3)

Global Const $MB_OK = 0 ; One push button: OK

Global Const $MB_OKCANCEL = 1 ; Two push buttons: OK and Cancel

Global Const $MB_ABORTRETRYIGNORE = 2 ; Three push buttons: Abort, Retry, and Ignore

Global Const $MB_YESNOCANCEL = 3 ; Three push buttons: Yes, No, and Cancel

Global Const $MB_YESNO = 4 ; Two push buttons: Yes and No

Global Const $MB_RETRYCANCEL = 5 ; Two push buttons: Retry and Cancel

Global Const $MB_CANCELTRYCONTINUE = 6 ; Three buttons: Cancel, Try Again and Continue

Global Const $MB_HELP = 0x4000 ; Adds a Help button to the message box. When the user clicks the Help button or presses F1, the system sends a WM_HELP message to the owner.

; Displays an icon in the message box

Global Const $MB_ICONNONE = 0 ; Stop-sign icon

Global Const $MB_ICONSTOP = 16 ; Stop-sign icon

Global Const $MB_ICONERROR = 16 ; Stop-sign icon

Global Const $MB_ICONHAND = 16 ; Stop-sign icon

Global Const $MB_ICONQUESTION = 32 ; Question-mark icon

Global Const $MB_ICONEXCLAMATION = 48 ; Exclamation-point icon

Global Const $MB_ICONWARNING = 48 ; Exclamation-point icon

Global Const $MB_ICONINFORMATION = 64 ; Icon consisting of an 'i' in a circle

Global Const $MB_ICONASTERISK = 64 ; Icon consisting of an 'i' in a circle

Global Const $MB_USERICON = 0x00000080

; Indicates the default button

Global Const $MB_DEFBUTTON1 = 0 ; The first button is the default button

Global Const $MB_DEFBUTTON2 = 256 ; The second button is the default button

Global Const $MB_DEFBUTTON3 = 512 ; The third button is the default button

Global Const $MB_DEFBUTTON4 = 768 ; The fourth button is the default button.

; Indicates the modality of the dialog box

Global Const $MB_APPLMODAL = 0 ; Application modal

Global Const $MB_SYSTEMMODAL = 4096 ; System modal

Global Const $MB_TASKMODAL = 8192 ; Task modal

; Indicates miscellaneous message box attributes

Global Const $MB_DEFAULT_DESKTOP_ONLY = 0x00020000 ; Same as desktop of the interactive window station

Global Const $MB_RIGHT = 0x00080000 ; The text is right-justified.

Global Const $MB_RTLREADING = 0x00100000 ; Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems.

Global Const $MB_SETFOREGROUND = 0x00010000 ; The message box becomes the foreground window

Global Const $MB_TOPMOST = 0x00040000 ; The message box is created with the WS_EX_TOPMOST window style.

Global Const $MB_SERVICE_NOTIFICATION = 0x00200000 ; The caller is a service notifying the user of an event.

Global Const $MB_RIGHTJUSTIFIED = $MB_RIGHT ; Do not use, see $MB_RIGHT. Included for backwards compatibility.

; Indicates the button selected in the message box

Global Const $IDTIMEOUT = -1 ; The message box timed out

Global Const $IDOK = 1 ; OK button was selected

Global Const $IDCANCEL = 2 ; Cancel button was selected

Global Const $IDABORT = 3 ; Abort button was selected

Global Const $IDRETRY = 4 ; Retry button was selected

Global Const $IDIGNORE = 5 ; Ignore button was selected

Global Const $IDYES = 6 ; Yes button was selected

Global Const $IDNO = 7 ; No button was selected

Global Const $IDCLOSE = 8 ; Close button was selected

Global Const $IDHELP = 9 ; Help button was selected

Global Const $IDTRYAGAIN = 10 ; Try Again button was selected

Global Const $IDCONTINUE = 11 ; Continue button was selected

Right-clicking an icon in the systray

Relies on the Windows key + "b", and moving to the app's index through the right arrow

#include <SysTray_UDF.au3> ;https://www.autoitscript.com/forum/topic/13704-systray_udf/

;highly modified version : https://www.autoitscript.com/forum/topic/103871-_systray-udf/

Const $MYAPP = "myapp.exe"

Const $MYAPP_WINDOW = "[TITLE:Blah; CLASS:Blah]"

Local $index = _SysTrayIconIndex ($MYAPP)

if not $index then Exit ConsoleWrite($MYAPP & " not found." & @CRLF)

ConsoleWrite(StringFormat("Index: %s" & @CRLF,$index))

Send('{LWINDOWN}b{LWINUP}')

Sleep(500)

Send('{RIGHT ' & $index & '}{ENTER}')

Sleep(500)

WinActivate(MYAPP_WINDOW)

GUI

AutoIt can be used to write graphical applications. As of 2018, there are two ways to do this: Either by writing your own code directly, or by using any of the numerous GUI creators such as GuiBuilderPlus (under current development) or the Koda GUI designer — which is included in the AutoIt installer, but hasn't been updated since 2010. Note that GUI designers only handle the GUI, not the code of the application: Any change you make to the GUI must be retrofitted into the application.

Some sources to learn how to write GUIs in AutoIt:

AutoIt supports the following widgets:

Basic GUI functions

Handling Events

Two ways to handle events: MessageLoop mode (default; actively polls the GUIGetMsg function; best for GUIs where the GUI is "king" and all you care about is waiting for user events) and OnEvent mode (enabled with Opt("GUIOnEventMode", 1); best for GUIs where the GUI is of secondary importance and your script has other tasks to perform in addition to looking after the GUI).

MessageLoop

While True
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
                Case $OK
                    MsgBox($MB_OK, "GUI Event", "You selected OK!")
                Case $Cancel
                    MsgBox($MB_OK, "GUI Event", "You selected Cancel!")
        EndSwitch
WEnd

OnEvent

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
 
Local $hMainGUI = GUICreate("Hello World", 200, 100)
Local $iOKButton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($iOKButton, "OKButton")
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
GUISetState(@SW_SHOW, $hMainGUI)
 
While True
  Sleep(100) ; Sleep to reduce CPU usage
WEnd
 
Func OKButton()
  ; Note: At this point @GUI_CtrlId would equal $iOKButton,
  ; and @GUI_WinHandle would equal $hMainGUI
  MsgBox($MB_OK, "GUI Event", "You selected OK!")
EndFunc   ;==>OKButton
 
Func CLOSEButton()
  ; Note: At this point @GUI_CtrlId would equal $GUI_EVENT_CLOSE,
  ; and @GUI_WinHandle would equal $hMainGUI
  MsgBox($MB_OK, "GUI Event", "You selected CLOSE! Exiting...")
  Exit
EndFunc   ;==>CLOSEButton

Basic loop

Here's how to create the GUI, perform some tasks, and then wait until the user hits the Esc key to close the app:

; Create GUI
Local $hGUI = GUICreate("Blah", 400, 300)
...
; Loop until the user exits.
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()

Constants

Edit box

Using the third option is used and setting it to "1" puts the carret at then end before appending text.

Use this to include a vertical scroll bar:

Local $aWindowClientArea_Size = WinGetClientSize($gui)
Local $EditBox = GUICtrlCreateEdit("", -1, -1,$aWindowClientArea_Size[0],$aWindowClientArea_Size[1],BitOR($ES_MULTILINE,$ES_READONLY,$WS_VSCROLL,$ES_AUTOVSCROLL))

Here's how to empty controls by relying on the fact that each control is assigned an integer that is incremented with each time control:

#include <WindowsConstants.au3>
#include <WinAPI.au3>
 
For $i=$FIRST to $LAST
  if _WinAPI_GetClassName(GUICtrlGetHandle($i))="Edit" Then
    GUICtrlSetData($i,"")
  EndIf
Next

Input box

Move caret to the beginning:

GuiCtrlSendMsg($INPUTCTRL, $EM_SETSEL, 0, 0)

Checkboxes

$sOptions = ((GUICtrlRead($BITRATE) = $GUI_CHECKED) ? "-b:v 450k ": "")

Radio buttons

The GUICtrlCreateGroup() assumes that widgets that follow belong to the group, with no need to specify the group's handle. The group will take of selecting/unselecting the buttons:

$Group1 = GUICtrlCreateGroup("My group", 8, 8, 113, 81)
$Blah = GUICtrlCreateRadio("Blah", 16, 24, 57, 25)

A simple way to check which of two buttons is selected:

$Choice = (GUICtrlRead($Blah) = $GUI_CHECKED) ? "Choice1" : "Choice2")

Launch long-running task

To keep the GUI responsive while launching a long-running task:

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>
 
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 623, 449, 279, 114)
$List1 = GUICtrlCreateList("", 0, 52, 622, 396)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
 
For blah
        ; to keep GUI responsive
        if GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
 
        ;long task
Next
 
;To keep the GUI open
While GUIGetMsg() <> $GUI_EVENT_CLOSE ;no need for Sleep(10)
WEnd

Alternatives: Run the GUI in OnEventMode by launching the task when pushing a button, or launch the long-running task in a thread (forum):

; Changes to OnEvent mode
Opt('GUIOnEventMode', 1)
 
; Launch long-running task
GUICtrlCreateButton("Button1", 100, 20, 200, 30)
GUICtrlSetOnEvent(-1, 'Function1') ; run Function1 when pressed
 
; Runs the GUIExit() function if the GUI is closed
GUISetOnEvent($GUI_EVENT_CLOSE, 'GUIExit')
 
; Shows the GUI after the function completes
GUISetState(@SW_SHOW)
 
While 1
        Sleep(500)
WEnd
 
Func Function1()
; Long running task here
EndFunc
 
; This function makes the script exit when the GUI is closed
Func GUIExit()
Exit
EndFunc

ADD thread mode here

To prevent flicker when adding items in listbox

_GUICtrlListBox_BeginUpdate($idListBox)

...

_GUICtrlListBox_EndUpdate($idListBox)

Double-clicking in a listbox

;it's recommended to return from WM_COMMAND as fast as possible:
;For this, use a dummy control, and process the event in eg. main loop
 
Global $hMain, $cList1, $cDummy
 
$hMain = GUICreate('Example', 900, 300)
$cDummy = GUICtrlCreateDummy()
$cList1 = GUICtrlCreateList('', 0, 0, 300, 300)
GUICtrlSetData($cList1,"item1|item2")
 
;required to handle double-click on list
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
 
GUISetState(@SW_SHOW, $hMain)
 
;in GUI loop, don't refer to listbox, or double-clicks won't be properly handled
While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cDummy
            if GUICtrlRead($cDummy) = $LBN_DBLCLK Then
                ConsoleWrite('Double clicked: ' & GUICtrlRead($cList1) & @CRLF)
            EndIf
    EndSwitch
    Sleep(10)
WEnd
 
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg
    Local $hWndFrom, $iCtrlID, $iNotificationCode, $hWndListBox
 
    $hWndListBox = (Not IsHWnd($cList1)) ? (GUICtrlGetHandle($cList1)) : ($cList1)
 
    $iCtrlID = BitAND($wParam, 0xFFFF) ; Low Word isn't a handle
    $iNotificationCode = BitShift($wParam, 16) ; Hi Word
 
    Switch $lParam  ; Control handle
        Case $hWndListBox
            GUICtrlSendToDummy($cDummy, $iNotificationCode)
    EndSwitch
    Return 'GUI_RUNDEFMSG' ; GUI_RUNDEFMSG
EndFunc

Progress bar

The progress bar expects a maximum of 100

For $i = 0 To 100
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
        GUICtrlSetData($Progress1, $i)
Next

If max is not 100:

Local $Max = UBound($aArray) -1
For $picindx = 1 to $Max
        if GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
        GUICtrlSetData($Progress1, ($picindx/$Max) * 100)
Next

Centering the window

Don't specify the "left,top" params, or even the "width,heigh":

$Form1 = GUICreate("Blah", 397, 357)

$Form1 = GUICreate("Blah")

Simple GUI loop just to keep window open

Simplest code:

While GuiGetMsg() <> $GUI_EVENT_CLOSE
WEnd

Alternative:

Do
        $idMsg = GUIGetMsg()
        If $idMsg = $idButton Then
            ;do stuff
        EndIf
Until $idMsg = $GUI_EVENT_CLOSE

Or even:

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()

Don't use Sleep in an inner loop. According to the help file, a call to sleep() isn't necessary since GuiGetMsg() " automatically idles the CPU when required so that it can be safely used in tight loops without hogging all the CPU."

While True
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $OK
                        While True
                                ;So Cancel works while busy here
                                $nMsg = GUIGetMsg()
                                if $nMsg = $GUI_EVENT_CLOSE or $nMsg = $Cancel Then ExitLoop
                                â€¦
                                ; will make GUI unresponsive: GUIGetMsg() automatically idles the CPU when required
                                ;BAD Sleep(1000)
                        WEnd
 
                Case $Cancel,$GUI_EVENT_CLOSE
                        Exit
        EndSwitch
WEnd

Plain window to output text

The window contains a single widget, just to output text:

#Region #GUI section
Local $gui = GUICreate("Test", 360, 333)
ControlSetText("", "", $gui, "New title")
Local $aWindowClientArea_Size = WinGetClientSize($gui)
Local $EditBox = GUICtrlCreateEdit("", -1, -1,$aWindowClientArea_Size[0],$aWindowClientArea_Size[1],bitor($ES_MULTILINE,$ES_READONLY,$ES_AUTOVSCROLL))
GUISetState()
#EndRegion
 
While True
    if GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
 
    GUICtrlSetData($EditBox, ControlGetText("","",$EditBox) & ".")
WEnd

This works, but it doesn't close when the user hits the Escape key, and doesn't support MsgBox():

SplashTextOn($SPLASH_TITLE, "", -1, -1, -1, -1, $DLG_TEXTLEFT, "", 24)
Local $iReturn = Run($LINE, $WORKDIR, @SW_HIDE,$STDOUT_CHILD + $STDERR_CHILD)
If @error Then Exit MsgBox($MB_ICONERROR, "Error", "Run failed." & @CRLF & @CRLF & StderrRead($iReturn))
While True
        ControlSetText($SPLASH_TITLE, "", "Static1", $iIndex )
WEnd
ConsoleWrite("Done." & @CRLF)
Sleep(1000)
SplashOff()

Listview

a.k.a. poor man's grid control.

Using core functions

https://www.autoitscript.com/autoit3/docs/functions/GUICtrlCreateListView.htm

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WindowsConstants.au3>
 
GUICreate("listview items", 220, 250, 100, 200, -1, $WS_EX_ACCEPTFILES)
 
Local $idListview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 200, 150) ;,$LVS_SORTDESCENDING)
Local $idButton = GUICtrlCreateButton("Value?", 75, 170, 70, 20)
Local $idItem1 = GUICtrlCreateListViewItem("item2|col22|col23", $idListview)
 
GUISetState(@SW_SHOW)
 
While True
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
      ExitLoop
 
    Case $idListview
      MsgBox($MB_SYSTEMMODAL, "listview", "clicked=" & GUICtrlGetState($idListview), 2)
 
    Case $idButton
      MsgBox($MB_SYSTEMMODAL, "listview item", GUICtrlRead(GUICtrlRead($idListview)), 2)
 
  EndSwitch
WEnd

Using the core functions only, the ListView control doesn't react to (double-)clicks on the grid, and neither does it allow multiple selections. Combining the core functions with the GuiListView UDF is the easier solution to using the UDF only.

Using core functions + GuiListView UDF

https://www.autoitscript.com/autoit3/docs/libfunctions/GUI%20GuiListView%20Management.htm

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <GuiImageList.au3>
 
Local Const $iStyle = BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $WS_HSCROLL)
Local Const $iExStyle = BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)
 
Local $hGUI = GUICreate("ListView Create (v" & @AutoItVersion & ")", 400, 300)
Global $cListView = GUICtrlCreateListView("Col1|Col2|Col3", 2, 2, 394, 268, $iStyle, $iExStyle)
 
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
 
GUICtrlCreateListViewItem('Item 0 - Subitem 0|Item 0 - Subitem 1|Item 0 - Subitem 2', $cListView)
 
_GUICtrlListView_SetColumnWidth($cListView, 0, 120)
_GUICtrlListView_SetColumnWidth($cListView, 1, 120)
_GUICtrlListView_SetColumnWidth($cListView, 2, 120)
 
GUISetState(@SW_SHOW)
 
;To handle other events, use OnEvent mode?
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
GUIDelete()
 
;Note: Reads $cListView, so must be global
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hListview
    If Not IsHWnd($cListView) Then $hListview = GUICtrlGetHandle($cListView)
 
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListview
            Switch $iCode
                Case $NM_DBLCLK
                    $tNMITEMACTIVATE = DllStructCreate($tagNMITEMACTIVATE, $lParam)
                    ConsoleWrite('Double clicked item: ' & $tNMITEMACTIVATE.Index & ', Subitem: ' & $tNMITEMACTIVATE.Subitem & @CRLF)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Using GuiListView UDF only

$g_hListView = _GUICtrlListView_Create($hGUI, "", 2, 2, 394, 268, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $WS_HSCROLL))
_GUICtrlListView_SetExtendedListViewStyle($g_hListView, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES))
_GUICtrlListView_InsertColumn($g_hListView, 0, "Column 1", 100)
_GUICtrlListView_InsertColumn($g_hListView, 1, "Column 2", 100)
_GUICtrlListView_InsertColumn($g_hListView, 2, "Column 3", 100)
_GUICtrlListView_AddItem($g_hListView, "Col 1")        
_GUICtrlListView_AddSubItem($ListView1, 0, "Col 2", 1)
_GUICtrlListView_AddSubItem($ListView1, 0, "Col 3", 2)
...
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
...
EndFunc   ;==>WM_NOTIFY

Working with COM libraries

The Help file contains two sections: "Obj/COM Reference", and "Obj/COM functions Reference". Since they're not part of AutoIt, and hence auto-completion isn't available, working with COM objects requires reading their respective documentations to figure things out.
In addition to Obj*() and IsObj(), AutoIt provides two extra syntaxes to make things easier: With..EndWith, and For..In (the latter can also be used with AutoIt's arrays, not just COM objects; The For..In syntax is needed to enumerate a collection's elements).

$oXmlDoc = ObjCreate("Microsoft.XMLDOM")
If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "COM Error", "@error = 0x" & Hex(@error)))
 
If IsObj($$oXmlDoc) Then
  With $oXmlDoc
    .mymethod($blah)
    If .parseError.errorCode Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "Some error", .parseError.reason)
  EndWith
EndIf
 
;Enumerate a collection of objects
For $iCell In $oExcel.ActiveSheet.Range("A1:O16")
  ;blah
Next

There are two ways to handle COM errors: Using a generic error function by AutoIt, or the object's specific events.

Local $oComErr = ObjEvent("AutoIt.Error", "com_error_handler")
#forceref $oComErr
...
Func com_error_handler($oError)
    With $oError
        ConsoleWrite(@CRLF & "COM ERROR DETECTED!" & @CRLF)
        ConsoleWrite("  Error ScriptLine....... " & .scriptline & @CRLF)
        ConsoleWrite("  Error Number........... " & StringFormat("0x%08x (%i)", .number, .number) & @CRLF)
        ConsoleWrite("  Error WinDescription... " & StringStripWS(.windescription, $STR_STRIPTRAILING) & @CRLF)
        ConsoleWrite("  Error RetCode.......... " & StringFormat("0x%08x (%i)", .retcode, .retcode) & @CRLF)
        ConsoleWrite("  Error Description...... " & StringStripWS(.description   , $STR_STRIPTRAILING) & @CRLF)
    EndWith
    Exit
EndFunc

Not all Object support events, if any. AutoItCOM can only receive 'dispatch' type events. Also, you need to know the names of the Events the Object could generate, including their arguments. Here's an example:

Local $oEventObject = ObjEvent($oIE, "IEEvent_", "DWebBrowserEvents") ; Start receiving Events.
...
Func IEEvent_StatusTextChange($sText)
...
EndFunc   ;==>IEEvent_StatusTextChange
 
Func IEEvent_BeforeNavigate($sURL, $iFlags, $sTargetFrameName, $dPostData, $sHeaders, $bCancel)
...
EndFunc   ;==>IEEvent_BeforeNavigate

COM objects are automatically released when the script exists, but they can be released manually by assiging a value of zero:

Local $oHTTP = ObjCreate("winhttp.winhttprequest.5.1") ; Object is created
$oHTTP = 0 ; Object is deleted

The "OLE/COM Object Viewer" (more infos) is a handy tool to get a peek on all COM libraries currently installed on your system. By default, oleview.exe will be installed in C:\Program Files\Resource Kit\. It requires downloading the IVIEWERS.DLL file separately.
Surprisingly, the OLE/COM Object Viewer application doesn't provide a search function: To find an object, you'll have to manually look it up in the Type Libraries section, eg. "Microsoft XML" — start typing to find an object. Right-clicking can copy its GUID into the clipboard, which can then be looked for in the Registry.

The "VersionIndependentProgID" info is to be used when calling Obj*().

"AutoIt uses the IDispatch interface for automation. This interface 'exposes' all scriptable methods and properties that the object supports. If there is no IDispatch interface for an object, you can't use the object in an AutoIt script." Note: For some reason, the application returns this error when right-clicking on an object's IDispatch interface: "IDataObject interface viewer only supports IID_IDataObject.

Some information about the Viewer is available in the help file's "Obj/COM Reference" section.

Some COM resources on the internet:

Working with XML/HTML files

As of 2023, the best solution is to work directly with Microsoft's MSXML COM server through AutoIt's ObjCreate(). mLipok's XML.au3 UDF wrapper (Previously XMLWrapperEx.au3) to Microsoft.XMLDOM (msxmlX.dll is currently at version 6) is incomplete and hasn't been updated since 2017. If you don't need to save changes back to XML, TheXman's jq.au3 can convert XML to JSON using jq.exe.

Important: If search fails even though the XPath is correct, it could be due to namespaces. To check, either get rid of them in the input file, or use a regex for that purpose — StringRegExpReplace(FileRead($XML_FILE), "(xmlns:?[^=]*=[""][^""]*[""])", "") .

List of UDF's:

Useful tools/resources to work with XML

Using the MSXML COM server

If you don't know how to work with XML, it can't hurt to first read a bit about MSXML and DOM, along with XPath.

Reading and searching

$sXML = FileRead("your.xml")
Local $oXML = ObjCreate("Microsoft.XMLDOM")
$oXML.loadxml($sXML)
$oIncidents = $oXML.SelectNodes("//TrafficIncident")
For $oIncident In $oIncidents
    $oLatitude = $oIncident.SelectSingleNode("./Point/Latitude")
    ConsoleWrite($oLatitude.text & @CRLF)
Next

Catching errors

; Error monitoring. This will trap all COM errors while alive.
; This particular object is declared as local, meaning after the function returns it will not exist.
Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc

mLipok's XML.au3 UDF

As of 2023, the latest release is 1.1.1.13 from March 2017. It requires including xml.au3 and ADO_CONSTANTS.au3. _XMLDomWrapper_1.0.3.98_CN.au3 is only included for historical reference.

Sources to learn:

Before asking for help in the thread, make sure you use the latest release of the UDF, and provide the versions of msxmd.dll, the UDF, AutoIt, and SciTE you're using. If you get a "Automation server can't create object", make sure msxml.dll is actually installed, and up to date.

To find data, use XPath to the max.

That UDF might be good enough for your needs, although development stopped in 2017, and some functions are either not as easy to use as they should be, or missing altogether:

Since multiple UDFs were written over time, I assume working with MSXML exclusively through a COM object is much harder — or people wouldn't have bothered. Regardless, since XML is getting a bit old, an alternative could be to convert XML to JSON, and use JSON functions instead.

Functions

A function returns either OK/NOK, a string, an array, or a collection — a collection might need to be turned into an array before further use (after always checking for for success/error) eg. _XML_GetAllAttribIndex() + _XML_Array_GetAttributesProperties().

Check UDF version

ConsoleWrite("UDF Version: " & _XML_MiscProperty_UDFVersion() & @CRLF)

Check encoding

ConsoleWrite(_XML_MiscProperty_Encoding()  & @CRLF)

Display contents

$oXmlDocIn = _XML_CreateDOMDocument() ; create object

_XML_Load($oXmlDocIn, "myfile.xml") ;To read from a string, use _XML_LoadXML()

ConsoleWrite(_XML_Tidy($oXmlDocIn) & @CRLF)

Tidy up

https://www.autoitscript.com/forum/topic/176895-xmlau3-beta-support-topic/?do=findComment&comment=1294608

Note: "The standalone="no" directive comes from the _XML_Tidy command"

Local $oXMLDoc = _XML_CreateDOMDocument()
_XML_Load($oXMLDoc, "myfile.xml")
_XML_Load($oXMLDoc, _XML_TIDY($oXMLDoc))
$sXML = _XML_Tidy($oXmlDocIn, "UTF-8")
ConsoleWrite($sXML & @CRLF)
_XML_SaveToFile($oXMLDoc, "settings.xml") 

Read data

MsgBox($MB_ICONINFORMATION, "", _XML_NodeExists($oXMLDoc, "Settings/node0")) ; Return 1 ok
 
Local $oNode = _XML_SelectSingleNode($oXMLDoc, "Settings/node0")
 
MsgBox($MB_ICONINFORMATION, "", _XML_GetNodeAttributeValue($oNode, "type") & @CRLF & "@Error Code :" & @error) ; return 0 | @error code = 7

Find number of nodes (elements)

$aRET = _XML_GetNodesCount($iRET, "/catalog/book")

Find one/multiple elements

To get just a single node:

Const Local $node = "/foo/bar"
Local $oNode = _XML_SelectSingleNode($oXMLDocIn, $node)
If @error Then
        ;Create new node
Else
        ;Local $stuff = _XML_GetValue($oXmlDocIn, $node)
        ;_ArrayDisplay($stuff, '$stuff')
        ;MsgBox($MB_OK,"Found2",$stuff[1])
        ;Simpler alternative
        MsgBox($MB_OK,"Found",$oNode.Text)
EndIf

To get multiple nodes:

$nodes = _XML_SelectNodes($oXMLDoc, '//Task')
If @error Then
    MsgBox($MB_ICONERROR, '_XML_SelectNodes @error:', XML_My_ErrorParser(@error))
Else
    _ArrayDisplay(_XML_Array_GetNodesProperties($nodes))
EndIf
 
_XML_SelectNodes($oXMLDoc, "//track")
If @error Then
        MsgBox($MB_ICONERROR, 'Error 1', _XML_ErrorParser_GetDescription($oXMLDoc))
Else
        Local $iNodesCount = @extended
        For $iItem_idx = 1 To $iNodesCount ; alternative: $allTimes.length
                Local $oChilds_Coll = _XML_SelectNodes($oXMLDoc, '//playlist/trackList/track[' & $iItem_idx & ']/*')
                Local $aNodesColl = _XML_Array_GetNodesProperties($oChilds_Coll)
                If @error Then
                        MsgBox($MB_ICONERROR, 'Error 2', _XML_ErrorParser_GetDescription($oXMLDoc))
                Else
                        _ArrayDisplay($aNodesColl, 'Example_1__XML_SelectNodes ' & $iItem_idx)
                EndIf
        Next
EndIf

Edit an element's value

_XML_UpdateField($oXmlDocIn, "//name", "new value")
If @error Then ConsoleWrite('ERR:' & @error & @CRLF & ' EXT:' & @extended & @CRLF)

? No way to update element's value through its pointer from _XML_SelectSingleNode()?

; Name ..........: _XML_UpdateField

; Description ...: Update existing single node based on XPath specs.

; Name ..........: _XML_UpdateField2

; Description ...: Update existing node(s) based on XPath specs.

Edit an attribute's value

_XML_SetAttrib($oXMLDoc, '/MagellanClient/Version', 'Current', '1.5.1.7f')
If @error Then MsgBox($MB_OK, '', _XML_ErrorParser_GetDescription($oXMLDoc))

Create and write a file

CHECK

;_XML_CreateFile($sXML_FileFullPath, $sRoot[, $bUTF8 = False)
Local $oXMLDoc = _XML_CreateFile("settings.xml", "Settings", True)
 
Local $aAttr = ["type", "name"]
Local $aVal = ["Menu", "Test"]
;Removed: _XMLCreateChildNodeWAttr - as it was only duplicate/wrapper for _XML_CreateChildWAttr
MsgBox($MB_ICONINFORMATION, "Info", (_XMLCreateChildNodeWAttr($oXMLDoc, "Settings", "Node0", $aAttr, $aVal) ? "true" : "false") & @CRLF & "@Error Code : " & @error) ; return "false : @error 4"
 
_XML_Load($oXMLDoc, _XML_TIDY($oXMLDoc)) ;If Load() can read from RAM, what's the point of LoadXML()?
 
_XML_SaveToFile($oXMLDoc, "settings.xml") ;alternative: FileWrite("settings.xml", $oXMLDocTMP)

Catch errors

BAD _XML_MiscProperty_NotifyAll(True)
BAD _XML_MiscProperty_NotifyToMsgBox(False)
 
Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc_CustomUserHandler")
#forceref $oErrorHandler
 
; Add user ComError handler ; it will be used together with internal ComError handler
_XML_ComErrorHandler_UserFunction(_ErrFunc_CustomUserHandler)
 
Func _ErrFunc_CustomUserHandler($oError)
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
            @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
            @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
            @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
            @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
            @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
            @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc_CustomUserHandler

Q&A

What does it add to MSXML.DLL that can't be used directly through COM? Can't AutoIt work with COM objects?

Does MSXML handle HTML?

Is XPath always required to search for nodes?

How to read, navigate, edit? All through XPath, no equivalent to BS' find_(all)?

Does case matter, eg. are _XML_LoadXML() and _XML_LoadXml() the same? _XML_TIDY() vs. _XML_Tidy()?

What's the diff? ConsoleWrite($oXMLDocIn.xml) vs. ConsoleWrite($oXMLDocIn)

Why is encoding="UTF-8" gone in header when reading XML file?

Why does the UDF/MSXML add "standalone="no"" in the XML header?

What if XPath returns more than one element when calling selectSingleNode()? Is only the first one read?

From XML as JSON

An alternative to Microsoft's MXSML DLL is to use the TheXman's Powerful and flexible JSON Processing jq UDF wrapper to jq.exe (January 2019; jq.au3), and Xml2Json to convert XML to JSON (xml2json.au3). To get/set data, it relies on jq's filters.

Note that converting XML to JSON removes the difference between attribute and text (<element attribute="foo">bar</element>), and some XML files may need custom stylesheets or may need the XML file to be modified before transformation.

Provided there's a simple UDF to convert XML to JSON, it might be possible to use AspirinJunkie's JSON.au3 and get rid of the dependency on jq.exe. If not, it still offers the benefit of AutoIt syntax instead of jq filters to work with JSON.

Besides JSON having no notion of XML attributes, JQ — and therefore this UDF — can not save data back into XML.

Working with JSON files

2009 JSON (by Gabriel13) - RFC4627 compliant JSON encode/decode.

2013 JSON (by Ward) - JSMN - A Non-Strict JSON UDF. "jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be easily integrated into resource-limited or embedded projects."

2013 JSON (by ozmike) - Bridge to Native Windows JSON plus OO extension for AutoIt.

2015 JSONgen: JSON generator (by Jefrey) - UDF to generate JSON.

2019 jq (by TheXman) - Brings the power and flexibility of jq (an open-source command-line based JSON processor) to AutoIt.

2023 JSON (by AspirinJunkie) - Interacting with JSON data in AutoIt. "Probably the most common method to deal with JSON in AutoIt is the variant via JSMN. My minor dissatisfactions with this approach led me to write this UDF in the first place a few years ago." (no need for jsmn/jq binary?)

#include <JSON.au3> ;AspirinJunkie
 
$sString = FileRead("input.geojson")
$JSON = _JSON_Parse($sString)
 
$key = _JSON_Get($JSON, 'key1')
ConsoleWrite($key & @CRLF)
$key = _JSON_Get($JSON, 'key2')
ConsoleWrite($key & @CRLF)
 
$features = _JSON_Get($JSON, 'features')
For $I = 0 To UBound($features) - 1
    $name = _JSON_Get($JSON, 'features.['&$I&'].properties.name')
    ConsoleWrite($name & @CRLF)
    $coordinates = _JSON_Get($JSON, 'features.['&$I&'].geometry.coordinates')
    For $c = 0 To UBound($coordinates) - 1
        $coordinates = _JSON_Get($JSON, 'features.['&$I&'].geometry.coordinates.['&$c&']')
        ConsoleWrite($coordinates & @CRLF)
    Next
Next

Running DOS apps

Examples

Run, wait, display output

If you only want to run an application and don't need to display the output in real time:

Local $iReturn = Run($LINE, $WORKDIR, @SW_HIDE,$STDOUT_CHILD + $STDERR_CHILD)
If @error Then Exit MsgBox($MB_ICONERROR, "Error", "Run failed." & @CRLF & @CRLF & StderrRead($iReturn))
ProcessWaitClose($iReturn)
ConsoleWrite("Output:" & StdoutRead($iReturn) & @CRLF)

Display in GUI

A simpler alternative to a full-fleged GUI just to output text is to use SplashTextOn/Off():

#include <AutoItConstants.au3>
#include <WindowsConstants.au3>
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
 
Local Const $SPLASH_TITLE = "Run DOS app"
 
SplashTextOn($SPLASH_TITLE, "", -1, -1, -1, -1, $DLG_TEXTLEFT, "", 24)
 
Local Const $LINE = "c:\mydosapp.exe"
Local Const $WORKDIR = "c:\temp"
 
Local $iReturn = Run($LINE, $WORKDIR, @SW_HIDE,$STDOUT_CHILD + $STDERR_CHILD)
If @error Then Exit MsgBox($MB_ICONERROR, "Error", "Run failed." & @CRLF & @CRLF & StderrRead($iReturn))
 
Local $iIndex = 1
;catch Esc key to exit loop?
While True
        $sErrOutput = StderrRead($iReturn)
        if StringInStr($sErrOutput,"ERROR") then Exit ConsoleWrite("Error reported by app:" & @CRLF & $sErrOutput & @CRLF)
        if StringInStr($sErrOutput,"WARNING") then
                $sErrOutput = "Warning reported by app:" & @CRLF & $sErrOutput & @CRLF
                ConsoleWrite($sErrOutput)
        EndIf
 
        $sOutput = StdoutRead($iReturn)
        If @error Then ExitLoop
 
        ControlSetText($SPLASH_TITLE, "", "Static1", $iIndex )
        $iIndex += 1
WEnd
 
ControlSetText($SPLASH_TITLE, "", "Static1", "Done.")
Sleep(2000)
SplashOff() ;poof

Read StdOut while app running

Using a basic GUI with just an Edit box:

Local $iReturn = Run($LINE, $OUTPUTDIR, @SW_HIDE,$STDOUT_CHILD + $STDERR_CHILD)
If @error Then Exit MsgBox($MB_ICONERROR, "Error", "Run failed." & @CRLF & @CRLF & StderrRead($iReturn))
Local $sOutput
While True
    ;to keep GUI respnsive, if needed
    if GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
 
    $sErrOutput = StderrRead($iReturn)
    if $sErrOutput <> "" then Exit ConsoleWrite("Error reported by app:" & @CRLF & $sErrOutput & @CRLF)
 
    $sOutput = StdoutRead($iReturn)
    If @error Then ExitLoop ; no more to read
    ConsoleWrite($sOutput & @CRLF)
WEnd
;to keep GUI open, if applicable
While GuiGetMsg() <> $GUI_EVENT_CLOSE
WEnd

Write StdIn

Wait for item in StdOut

Write

GOTO 10

NO DOS https://www.autoitscript.com/forum/files/file/351-learn-to-program-using-free-tools-with-autoit/

NO TUTORIAL ON DOS https://www.autoitscript.com/autoit3/docs/

NO TUTORIAL ON DOS Learning to Script with AutoIt V3 (Last Updated 17 Feb 2010).zip

Autoit-1-2-3 http://www.autoitscript.com/forum/index.php?act=attach&type=post&id=10824

Run()

Handle StdErr

Tips

If you…

Functions and constants

Questions

When is StdioClose() required/recommended?

Why use "@ComSpec"? Run(@ComSpec & " /C DIR c:\test1")

What is a Console application?

Run*() vs. ShellExecute*()?

Missing CRLF in StdOut()?

Do Std*() still contain data after running RunWait()?

Do StOut*() contain all the data after running RunWait(), or are their buffers limited in size, and will only contain the latest data after RunWait() exits? In that case, what is the right way to use Str*Read() to not miss any?

What is the right way to interact with a CLI app using StdInWrite() + Std*Read()?

How to read Stdout and Stderr separately, to know what an error occured?

How many bytes can the Stdout buffer contain?

Is there a risk of missing bytes while reading the Stdout buffer?

Using SQLite

AutoIt provides multipe UDFs to work with SQLite. Confusingly, the one included in the installer provides multiple ways to send a SELECT, but the experts say that Exec() should be used to write (INSERT, UPDATE, DELETE), GetTable[2d] should be used to read (SELECT), while Query*() + Fetch*() should be ignored entirely, although _SQLite_QuerySingleRow() works fine to fetch a single row:

$iRval = _SQLite_QuerySingleRow($hDskDb, $hQuery, $aResult)
if @error then Exit MsgBox($MB_ICONERROR + $MB_SYSTEMMODAL, "SQLite Error", @error & @CRLF & $iRval & @CRLF)
_ArrayDisplay($aResult, "Results from the query")

SQLite.au3 should always be included, but SQLite.dll.au3 is optional and seems to be used in _SQLite_SQLiteExe to access SQLite through its EXE instead of the DLL ("If included, the SQLite version is used.").

#include <Array.au3>
#include <SQLite.au3>
 
_SQLite_Startup() ; Load the DLL
If @error Then Exit MsgBox(0, "Error", "Unable to start SQLite, Please verify your DLL")
 
Local $sDatabase = @ScriptDir & '\SQLiteTestDatabase.db'
Local $hDatabase = _SQLite_Open($sDatabase) ; Create the database file and get the handle for the database
 
_SQLite_Exec($hDatabase, 'CREATE TABLE People (first_name, last_name);')
_SQLite_Exec($hDatabase, 'INSERT INTO People (first_name, last_name) VALUES ("Timothy", "Lee");')
 
Local $aResult, $iRows, $iColumns
 
;_SQLite_GetTableData2D() omits column names
_SQLite_GetTable2d($hDatabase, 'SELECT * FROM People;', $aResult, $iRows, $iColumns)
 
;_ArrayDisplay($aResult, "Results from the query")
;Alternative: SQLite_Display2DResult()
;Row 0 = column names
;simple way to access columns by names instead of indexes
Local Enum $eKey, $eFirstName, $eLastName
For $iRow = 1 To UBound($aResult) - 1
    ConsoleWrite('Loading row: ' & $iRow & @CRLF)
    ConsoleWrite('     id: ' & $aResult[$iRow][eKey] & @CRLF)
    ConsoleWrite('  title: ' & $aResult[$iRow][eFirstName] & @CRLF)
    ConsoleWrite(' animal: ' & $aResult[$iRow][eLastName] & @CRLF)
Next
 
_SQLite_Close($hDatabase)
_SQLite_Shutdown()

Driving a web application

As of 2023, there are two solutions currently maintained:

IUIAutomation

IUIAutomation can be used for multiple applications, and is based on the Microsoft automation API

WebDriver (Selenium)

WebDriver UDF : AutoIt solution to use the Selenium WebDriver interface for automation. Most popular browser support automation via this method, @Danp2 wrote a UDF for that. Incidently, Selenium's WebDriver can also be use with Python or Javascript. Alternative to Selenium IDE, which is a browser extension (Selenium RC was merged into WebDriver.)

Requirements

Important: All the required files above must be unzipped at the root of your "User Include Folder", ie. where you keep your personal UDF files, so that wd_demo.au3 can find them — It won't look in sub-directories.

Usage

The wd_demo.au3 is used to check that everything works OK, while wd_core.au3 and wd_helper.au3 contain code that you need to drive a browser.

As of April 2021, there seems to be no tutorial. To learn how to use the WebDriver UDF:

Accessing Outlook

COM

$oOutlook = ObjCreate("Outlook.Application")

OutlookEX UDF

https://www.autoitscript.com/forum/topic/126357-outlookex-udf-help-support/

After installing OutlookEX UDF per its Readme, run Outlook, and use the following script to read the data from its To-Do List panel, sorted through Last Modified:

#include "OutlookEX.au3"
 
Global $oOutlook = _OL_Open()
If @error <> 0 Then Exit MsgBox($MB_ICONERROR, "OutlookEX UDF", "Error creating a connection to Outlook. @error = " & @error & ", @extended = " & @extended)
 
$aFolder = _OL_FolderAccess($oOutlook, "", $olFolderToDo)
 
Global $aResult = _OL_ItemFind($oOutlook, $aFolder[1], $olTask, "", "", "", "EntryID,Subject,LastModificationTime")
If @error Then
    MsgBox($MB_ICONERROR, "OutlookEX UDF - _OL_ItemSearch Example Script", "Error running _OL_ItemSearch. @error = " & @error & ", @extended = " & @extended)
Else
    _Arraydisplay($aResult)
EndIf
 
_OL_Close($oOutlook)

Editing Contacts in Outlook with OutlookEX

  1. Download and unzip the latest release of OutlookEx UDF (help thread and wiki)
  2. Copy OutlookEX.au3 and OutlookEXConstants.au3 into AutoIt3\Include
  3. If using the Scite editor, copy au3.user.calltips.api into AutoIt3\SciTE\api (append if file already exists), and copy au3.userudfs.properties into AutoIt3\SciTE\properties (ditto)
  4. Launch Outlook
  5. Run this code:

SciTE4AutoIt3 issues

If you do want to make manual changes to SciTE settings, it is best to do this in the "User Option File" because the installation of a new version will override the settings of the SciteGlobal.properties and au3.properties files. See the SciTE Documentation for all possible settings and User Options File for more details. All of these Configuration files can be found under the <Options> menu.
https://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/Scitedoc/SciTEDoc.html
https://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/SciTE4AutoIt3-user-options-file.html

Hit CarriageReturn : sometimes (eg. Else/EndIf), SciTE doesn't line up as expected (always lines up at col 0), so user hit TAB one or more times SciTE.AutoIt.wrong.indent.png

AutoIt: Always check for undeclared and unused variables? In au3.properties?

https://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3.html

Recover +/- keys on keypad

Edit C:\Users\blah\AppData\Local\AutoIt v3\SciTE\SciTEUser.properties to overrule the following parameter:

# User defined key commands
user.shortcuts=\
Ctrl+Shift+V|IDM_PASTEANDDOWN|\
Ctrl+PageUp|IDM_PREVFILE|\
Ctrl+PageDown|IDM_NEXTFILE|\
Ctrl+F1|IDM_HELP_SCITE|

Do not edit C:\Program Files (x86)\AutoIt3\SciTE\SciTEGlobal.properties

Script built with Au3Record.exe doesn't run

myscript..au3 (1) : ==> Unknown function name.: _WinWaitActivate("classname=TfrmPref","")

If you just copy/paste the output instead of what's actually saved in a file, you'll be missing some User-defined functions (UDF) that Au3Record relies on:

#region --- Internal functions Au3Recorder Start ---
Func _Au3RecordSetup()
        Opt('WinWaitDelay',100)
        Opt('WinDetectHiddenText',1)
        Opt('MouseCoordMode',0)
EndFunc
 
Func _WinWaitActivate($title,$text,$timeout=0)
        WinWait($title,$text,$timeout)
        If Not WinActive($title,$text) Then WinActivate($title,$text)
        WinWaitActive($title,$text,$timeout)
EndFunc
 
_AU3RecordSetup()
#endregion --- Internal functions Au3Recorder End ---

Script built with Au3Record.exe can't find application window

There is a bug with release 3.3 which uses "classname=myclass" instead of "[CLASS:myclass]".

In SciTE, what's the difference between Compile, Build, and Go?

Compile displays a dialog to set options, while Build doesn't.

No PDF or CHM for tutorial? https://www.autoitscript.com/autoit3/docs/

Scite's Tools: Compile vs. Build vs. Go?

Pressing Ctrl-F5 will run Tylo's AutoIt3 syntax checker, which will syntax check the script.

Compile (CTRL+F7): Compile with options allowing to make all kinds of changes to the target EXE like Ico and resource information. Displays a dialog box to change parameters.

Build (F7): Compiles with default options. You can create an executable (.exe) of your script. SciTE will run the Aut2Exe program and compile the script. Run AutoIt3Wrapper which will run Au3Check first and then Aut2EXE. Optionally many other things defined by the #AutoIt3Wrapper_ Directives.

Go (F5): Pressing just F5 will run Au3Check and then, if no errors/warnings are found, run AutoIt3.exe to run the script.

In Scite, hit CTRL+F1 for more infos.

Infos

Gotchas

Concatenating strings

You must use "&", not "+":

$myvar = "First line " & @CRLF & "Second line"

Send() can't identify a window

The Send() function sends a string to whatever window is active, ie. it's not possible to tell it to only send data to a specific window. So if you're using a loop, add a WinWaitActive() to make sure you're no sending stuff in a totally different window:

AutoItSetOption("SendKeyDelay",0)
for $index = 1 to $pages
    ;Just to make sure we are sending keystrokes to the right window
    WinWaitActive("Acme - Iron")
 
    Send("^l")
    Sleep(500)
 
    $url = "http://www.acme.com/search.php?page=" & $index & "{ENTER}"
    Send($url)
 
    ;Wait 5s. There might be a better way to check that page download has completed
Sleep(5000)
Next

Q&A

Using Local/Global outside functions?

Any variable declared outside a function is global, even if you defined it as local.

https://www.autoitscript.com/wiki/Variables_-_using_Global,_Local,_Static_and_ByRef

How to assign an icon when compiling a binary?

In SciTE: Tools > Compile. Use 32x32 pixels ICO file.

[Koda] Tools > Run form doesn't run code

It generates and pastes the code in SciTE (in test.au3), even after saving the GUI in a Koda file. Hitting F10 makes no difference.

When is #forceref required?

So AU3Check doesn't complain with "declared, but not used in func", error UNREFED. Can be turned off (-w- 5)

https://www.autoitscript.com/forum/topic/93732-forceref-answered/

When to use Global instead of Local?

Does AutoIt support dictionaries?

No, but Enum is a work-around:

Local Enum $eCat, $eDog, $eMouse, $eHamster
Local $aAnimalNames[4]
$aAnimalNames[$eCat] = 'Jasper' ; $eCat is equal to 0, similar to using $aAnimalNames[0]
$aAnimalNames[$eDog] = 'Beethoven'

Timeout = seconds or ms?

How to prevent compiling if undeclared variables?

AutoItSetOption("MustDeclareVars", 1)

Au3Stripper

Au3Check

How to handle time out? WinWaitActive("- Task", "",10)

WinWaitActive() vs. WinWaitActivate()?

How to leave an AutoIt script running in the icon bar, ready to pop up when hitting a given key sequence?

What's the difference between a window title and a window text?

Koda copies the source into SciTE instead of running the forum

In SciTE: Select Tools > Scite Config, click on the General 1 tab, and make sure "Choose default action for .au3 files" is set to "Run" instead of "Edit".

Resources