Windows GUI automation with AutoIt and Perl

This post contains some notes and thoughts from a short evaluation session for AutoIt3, a scripting tool that can be used to automate Windows GUI tasks by simulating user key strokes and mouse actions.

  • AutoIt is actively maintained, has a broad users base, and supports all versions of Windows.
  • AutoIt consists of a function library, a Basic-like programming language, and a compiler which allows you to create redistributable .exe scripts.
  • The recommended editor for AutoIt is a modified version of SciTE, available through the AutoIt web site.
  • As of April 2010, there is no Eclipse plug-in for AutoIt. The probability of such a plug-in ever being developed is low.
  • The function library focuses on window, keyboard, mouse, process management.
  • You can also create simple GUIs with AutoIt (if you must)
  • AutoIt scripts can call COM objects, providing access to additional functionality. There is a nice tutorial on oleview.exe included in AutoIt's help file, which may be of interest even if you don't need AutoIt as such.
  • Support for finding and manipulating controls other than by keyboard/mouse simulation and reading contents of GUIs seems missing or limited at best. For these reasons, AutoIt should be considered an automation tool to speed up repetitive tasks, not a full-featured GUI testing tool.

The longer I stay involved in software development business, the more I dislike the idea of inventing new specialized programming languages. Generally, by inventing a new language you are making life harder for everyone out there for two reasons:

  • established, well-known tools that took thousands of hours of development effort are likely to be useless with your new language
  • established, well-known libraries that took thousands of hours of development effort are likely to be more difficult to access from your new langugage
  • your new language will suffer from performance problems solved by thousands of hours of development effort invested into compilers for existing languages

A good reason for a custom programming language is if your users are so unsophisticated and their programming needs so limited that they would be overwhelmed by having to learn an existing scripting language. This might have actually been the argument when the first version of AutoIt was developed, but doesn't seem to be the case any longer.

Another good reason for a custom programming language is if you want to be cut dependencies. For example, write a custom binary compiler, which is just not there for a general-purpose scripting language. This is an advantage that AutoIt's author realized by making it possible to compile and redistribute AutoIt scripts as (small!) .exe files.

Anyway, when it comes to real-world scenarios found in my projects, I thought I might prefer to use AutoIt's automation functionality from a real-world language with a familiar syntax and direct access to tons of third-party libraries. Perl is one such language, hence I spent a little time testing AutoIt-Perl integration.

AutoIt ships with AutoItX, a DLL containing a COM object through which you can script AutoIt itself from within programs written in a language such as Perl. I experimented to see how well it goes. It does work, although there are some caveats. Below I include an example with some notes in comments.

use Win32::OLE;
use Win32::GUI;

# Note 1: we initialize OLE using Single-Threaded Appartment (STA) explicitly,
# as this is what the AutoIt COM object requires. If we don't do it,
# the default init via Win32::GUI::Window->new would initialize using
# Multi-Threaded Appartment (MTA), which would cause AutoIt calls to fail silently.

Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE());

$win = Win32::GUI::Window->new();

# Note 2: we must rely on ShellExecute from Win32::GUI rather than from AutoIt.
# Although there is a ShellExecute function available in AutoIt, it is not exported
# via the COM interface (AutoItX). In general, not everything available in AutoIt
# is exposed via AutoItX (which is bad).

# Note 3: when launching MS Access to open a database in a "trusted location"
# (i.e. macros allowed), then the path to the opened database must match exactly
# the path configured for the "trusted location". In particular, backslashes rather
# than slashes must be used as separators.

# Open MS Access database

$win->ShellExecute(
    "open",
    "msaccess.exe",
    "k:\\workspace\\nca_bo\\nca_bo.mdb",
    "k:\\workspace\\nca_bo",
    10);
    
# Note 4: see ShellExecute API doc for the meaning of constant 10
# in the above invocation.

my $Au3 = Win32::OLE->new("AutoItX3.Control");
# Wait till a pop-up message box appears
$Au3->WinWaitActive("Microsoft Office Access", "vom Web-Portal importieren");
# Simulate Alt-N keystroke to close message box
$Au3->Send("!n");
# Wait till an Access form appears
$Au3->WinWait("Hauptmenü");
# Simulate Alt-E keystroke to push a button on the form
$Au3->Send("!e");
# Wait till a pop-up message box appears
$Au3->WinWaitActive("Microsoft Office Access", "zum Web-Portal exportieren");
# Simulate Alt-N keystroke to close message box
$Au3->Send("!n");

Closing remarks:

  • To find out about the AutoItX COM interface, consult a .chm help file shipped with AutoIt, but separate from the main AutoIt help.
  • Lack of proper error reporting is a major risk when using Perl-AutoItX together, and possibly also for AutoIt alone. I got into situations where a command simply did not work, without any apparent error message (but in each case I could find a reason through closer investigation of the expected/actual syntax, Google).
  • I haven't tested the reliability of transferring data between AutoIt and Perl. Typically, integration between programming languages shows its flaws in the call API when it comes to exchanging more complicated data structures, passing parameters by reference etc.
  • Depending on the complexity level of the actual scripts, it may be actually tolerable to rely on coarse-grained integration: write scripts using AutoIt syntax and SciTE, then encapsulate them as functions into Perl.
  • In any case, putting serious functionality into AutoIt scripts that can be just as easily be implemented in a more mainstream language should be avoided when possible. For the particular combination of AutoIt and Perl, the general rule of thumb should be "as little AutoIt as necessary, as much Perl as possible".

1 comment:

Amy said...

Thanks, this help me a lot

Post a Comment