AutoIt is a language & framework to automate (mainly) Windows GUI application interactions. Though it has its own language but there are wrappers available for Python, C# etc too.
This write up target developers who want to automate Windows Desktop Applications but either do not know the right tool or want to enhance their skills using AutoIt.
Just like with any thing, there is either informed or amateur approach towards solving a problem. Developers who have never written Windows GUI applications will write AutoIt code that will depend too much on interactions with active GUI. While we can get maximum out of AutoIt when we rely less over such interactions. This amateur approach creates real issue when we have to interact with multiple desktop applications within same AutoIt script.
One solution to address these issues is to use _WinAPI_PostMessage function, where applicable. We will primarily use this function to interact with menus, otherwise our interactions may occur on wrong window.
Intent:
Want to automate Notepad;
- change display font
- write some text and
- save file
Downloads:
- AutoIt Full Installation
- AutoIt Script Editor
- GUI Inspection Tools:
- AutoIt Window Info (part of AutoIt Full Installation)
- Inspect
GUI Inspection:
In order to control GUI elements we will need the Windows Name, Controls ClassNameNN & Automation Ids of Notepad application. If you dont know how to find them using AutoIt Window Info and Inspect tools, watch this video (enable captions, if you want).
AutoIt Script
#include "WinAPI.au3" #include "WindowsConstants.au3" ; #INDEX# ======================================================================================================================= ; Title .........: Windows Desktop Applications Automation using AutoIt ; AutoIt Version : 3.3.14.2 ; Description ...: Automate Notepad for changing display font, writing some text and save file ; Author(s) .....: Ahmed Shaikh Memon (ahmedshaikhm) ; =============================================================================================================================== ; #VARIABLES# =================================================================================================================== Local $hWnd, $hWndFont, $hWndSaveAs Global $sFontName = "Arial" Global $sFileName = "tutorial_1" ; #CONSTANTS# =================================================================================================================== Global Const $__IDM_FONT = 33 Global Const $__IDM_SAVE = 3 Global Const $__IDC_FONT_NAME = 1001 ; Open Notepad Run("notepad.exe") Sleep(1000) ; Get Notepad's handle $hWnd = WinGetHandle("[Class:Notepad]") ; ; Display Font Change ; ; Click Format > Font menu _WinAPI_PostMessage($hWnd, $WM_COMMAND, $__IDM_FONT, 0) Sleep(1000) ; Handle Font window $hFontWin = WinGetHandle("Font") Sleep(1000) ; Select display font ControlSend($hFontWin,"", $__IDC_FONT_NAME, $sFontName) Sleep(2000) ; Save display font ControlClick($hFontWin, "", "Button5") Sleep(1000) ; ; Write text in Notepad ; ControlSend($hWnd, "", "Edit1","This is informed approach towards solving a problem") ; ; Save file ; ; Click File > Save menu _WinAPI_PostMessage($hWnd, $WM_COMMAND, $__IDM_SAVE, 0) Sleep(1000) ; Enter file name in the file open dialog box $hWndSaveAs = WinGetHandle("Save As") ControlSend($hWndSaveAs, "", "Edit1", $sFileName) Sleep(1000) ; Press the Save button on Save As prompt ControlClick($hWndSaveAs, "", "Button1") Sleep(1000)
This code is available as gist here
Explanation:
WinAPI.au3
& WindowsConstants.au3
contain definition or constants that will help to communicate particular command to window without visible interaction.
Global variables $hWnd
, $hWndFont
& $hWndSaveAs
will hold handles of Notepad Application, Font window & Save As windows, respectively. While s in $sFontName
& $sFileName
indicates that they are string. The advantage of following Naming Convention is that it helps create team factor in individuals thus a guess work can be utilized when multiple people are working on same code. Another benefit is that even if you open code after months, you can instantly recognize why particular variable was used.
$__IDM_FONT
& $__IDM_SAVE
are Menu IDs for sub-menus Font and Save respectively. We’ve identified them using Inspect tool. $__IDC_FONT_NAME
is the Control ID for text field for font name.
Run("notepad.exe")
is use to open the Notepad application. We can further improve it by using Run("notepad.exe", "", @SW_MAXIMIZE)
, this will make sure when Notepad is opened up, its window is minimize by default, specially useful when active window will disturb other application or if the computer (where this AutoIt script is being executed) distracts the person using it.
WinGetHandle()
is used so that we can send control actions or PostMessage()
to just related Window.
_WinAPI_PostMessage()
is a wraper to Win 32 API function PostMessage()
, this will click sub-menu item without need to have Notepad activated and visible. The function definition is within WinAPI.au3
, that is why it is included at the top. WindowsConstants.au3
contain the associated integer for $WM_COMMAND
constant
We’ve used ControlSend()
function, with particular window handle, so that control command is executed within specific window, otherwise Send()
function just send control command, even if (for any reason) your target window is not visible (minimized or something), the control might execute on wrong target if you use Send()
.
Sleep()
functions are used multiple times, because it take few milliseconds to load or close a window, for example Font & Save As windows open after some milliseconds, same while Font window is getting closed. If we dont use them the automation might not work properly.
Known Limitations:
The code is as brief as possible, there is a room to enhance and make it more professional
- We can open Notepad minimized
- The Font & Save As windows will be maximized by-default even if Notepad is opened minimized, therefore we can use
WinSetState()
function to explicitly minimize these windows - If the file already exist, we can add few lines of code to test if its asking for overwriting and then peform the desired action
- We can close Notepad after the automation using
WinClose()
- If your script is going to be deployed on variety of Windows oeprating system versions and different hardware specification machines, then add checks to see if intended control has successfuly executed. For instance, if I’ve to check if Notepad is really opened after
Run("Notepad.exe")
I would add something like;If Not WinExists($hWnd) Then ConsoleWrite("Notepad is not opened" & @CRLF) EndIf
Code Execution
Following animated gif shows what happen when you execute this code
Further Reading
For those who are interested in learning more should visit AutoIt’s official wiki & forum or search over StackOverflow, however make sure that you are coming up with intelligent (specific) question
Checkout Automate Skype Login using AutoIt post for a more practical example.
Credits
- Matt has pointed towards use of
PostMessage()
Menu IDs - AutoIt Forums got bunch of helpful guys who respond promptly
[…] Windows Desktop Applications Automation Using AutoIt 1 by r0ash | 0 comments on Hacker News. […]
[…] Windows Desktop Applications Automation Using AutoIt 1 by r0ash | 0 comments on Hacker News. […]
[…] Windows Desktop Application Automation Using AutoIt 5 by r0ash | 0 comments on Hacker News. […]
[…] Windows Desktop Application Automation Using AutoIt 11 by r0ash | 2 comments on Hacker News. […]
“Thank you ever so for you article post.Much thanks again. Great.”