Using AutoitX as a DLL in Python

We’ve been using AutoIt for a while now at the shop.  We do a LOT of repetitive stuff; for instance every computer that we clean up gets pretty much the exact same process.  Any time you find yourself performing the same steps over and over again on a computer by hand, that’s a sign you should be figuring out a way to let the computer do it for you (that’s what they’re for!) and AutoIt is one of the easiest ways to automate GUI interaction for those pesky Windows programs that don’t allow automation via command line options.

For a while now though I’ve been struggling with the fact that while AutoIt is really good at GUI automation, it isn’t very good at things like manipulating complex configuration data: a job which, unsurprisingly, often goes hand-in-hand with automating a few mouse clicks.  Often you’ll use automated clicks to install a program, but find that directly editing a config file is an easier way to configure it and that’s when AutoIt falls short.  It has file manipulation tools but they are very basic.  After all, it’s a GUI automation kit NOT a full fledged programming language; I don’t blame the AutoIt folks one bit for doing one thing and doing it well.  That’s the mantra us ‘nix folks live by!  So on and off over time I’ve sort of peaked around for a different solution, one that gives me both solid GUI automation and a full-fledged programming language with lots of good modules/libraries for various tasks.

Other GUI automation tools were eliminated pretty quickly.  I didn’t find anything that was a solid or feature complete as AutoIt.  That left me with looking for a way to glue multiple tools together that did NOT result in a house-of-cards setup that would be nearly impossible to replicate in the case of a failure or that would rely on the perfect alignment of planets to run reliably.  It didn’t take me long to realize that AutoItX was my best bet.

AutoItX (available on the main AutoIt download page) is basically a library version of AutoIt that can be used from other programming languages via a DLL or the Windows COM system.  It comes with some documentation for the interfaces, but for me the installer didn’t put it in the start menu; I had to dig in the program files folder to find the .chm file manually.  The trick was figuring out which programming language was best suited to the task of interfacing with the DLL and doing manipulation of config files in formats like INI and JSON.  The setup would have to be totally portable–we run our tools from a file share on our server and we can’t just go installing random runtimes on customer computers.  It also had to work well on Vista, 7, and 8.x, which makes things like PowerShell difficult since the varying versions provide different functions (e.g., PowerShell 1.0 doesn’t have native JSON support).  Recently my language of choice has been Python, and exploring that option is how I found what turned out to be a huge life saver: Portable Python.

Portable Python is exactly that: a portable python environment that can run from a local folder, UMS device like a flash drive, or a network file share.  Additional modules can be installed with relative ease, and it works on all the operating systems we support right now.  Python has lots of great modules for file management, file manipulation, config parsers for INI and JSON, pretty much everything I need.  Nicely enough, one can also easily call functions exported from a DLL file using an interface called ctypes.  They really mean for you to use AutoItX via COM in python, but that requires AutoItX to be installed locally which we aren’t going to do.

So here’s my setup: portable python and my scripts directory are stored in a file share on our server.  It’s easy to build a batch file that executes the portable python interpreter, passing my scripts as command line arguments to get them running without doing messy file-association mods on the customer PC’s.  The AutoItX DLL is also being hosted on a file share and my python script can copy that to a local folder then manually load it using ctypes.  Here’s an example of one of my scripts:

Please note that the big hurdle that I had to cross was related to Unicode strings.  At first I was just passing regular strings to the AutoIt functions (like WinWait) and they never matched any windows no matter what.  After some digging I found that AutoIt is expecting Unicode strings and it is assuming that all strings passed in are already Unicode and interpreting them as such.  Explicitly passing all strings as Unicode fixes that problem.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: