I'm aware of the history of the AutoHotKey project with respects to it's fork from AutoIt, and I hope a post like this doesn't stir things up. But the signal to noise ratio on searches I've done trying to compare the two is so poor that I ended up having to bite the bullet and simply try both. A comparison of the current technical abilities of each is something I looked for and couldn't find, so I did my own. What this comparison will do is leave behind the baggage of the past. What it won't be is completely objective, because I'm opinionated. The opinions will, however, be technically based and not based on history.
I haven't gone into huge depth, but in the hopes that this is helpful, here is what I've found:
Versions:
- AutoIt v3.3.14.2
- AutoHotKey v1.23.01
Both come with installers. AIT has a self-extracting zip with just the binaries, while AHK offers 32 and 64 bit versions of just the AHK binary itself as a separate download. No significant difference here. Both installers are reasonable. The AIT installer asks you to make the choice of whether to use 32 or 64 bit version language versions by default at install time, and it seems not to be able to change that default afterwards without uninstalling and reinstalling. It also asks you to decide at install time whether or not a double-click on a script will edit or run the script. Again, you can't seem to change that without uninstalling and reinstalling. AHK, however, doesn't give you the choice at all.
Development Environment
Neither project has a real development environment to speak of. AIT ships with a customized "lite" version of the text editor SciTE right in the installer, which is nice of them, but something I actually found a little annoying since SciTE itself is like Notepad++ with a lobotomy. While there is a similarly customized ScITE version for AHK separately maintained, it doesn't ship with any editor at all. This isn't necessarily a drawback - programmers are notoriously picky about their favourite editor - but what it also doesn't ship with (though it used to) is anything in the way of syntax highlighting support for the other common editors out there. What it does offer, though, are a few useful simple but surprisingly useful items in its task tray menu. I started this comparison with AHK and when I moved to AIT, I found the lack of the ability to reload a script or to see what script commands have been executed was far more disabling than I would have expected.
Both AHK and AIT allow the creation of a standalone executable for your script. Both label this process "compiling". The word is a slight misnomer, since compiling seems to be simply embedding the script as a resource inside a portable version of the runtime engine where it is interpreted just as it would be if you had run it normally. In AHK the script is embedded with no changes other than the removal of comments. In AIT the script is compressed before embedding it so it's harder to see what's going on under the hood. The claim is that it's tokenized and that there is a performance gain for compiling. If it is tokenized, then this is the same tokenization that is done when a script is run normally, since there is no real performance difference. This tokenization must not check for syntax, though, because in AIT having an incorrect function name, for example, is not caught at "compile" time. It's a run-time error that occurs only when the script attempts to execute that line of code. This is the case in both uncompiled and compiled scripts, which seems to indicate very little if anything in the way of preparsing is done. While neither AIT or AHK seem to actually compile the script, the process is still very useful. And even though it's not actually "compiled", I can think of no better name to use in the UI other than "Compile script", so I don't think either is trying to mislead.
The fact that in AIT bad function names are a run-time error caught only when they are executed is a serious issue that deserves further note. Certainly in solid production code every line should be executed during testing. For scripts, however, this is not always possible or even reasonable, and a simple typo or a character in the wrong place during editing can easily insert regression errors that are not found until after deployment.
Language
AIT syntax feels like an Algol-based third gen language. Similar, actually, to Pascal. Each multi-statement block type has its own discreet start and end syntax They do not all follow the same pattern, though, so expect to have a few syntax errors while you learn the ropes and remember that if closes with endif, but while closes with wend. All variables must be notated with a "$". All variables must also be declared before use. This isn't necessarily a bad thing, though. It's easy to change a variable name in AHK and end up with bugs when you forget to change all instances of it, while in AIT you usually end up with an error using an undeclared variable when that happens. Besides language declaration and flow constructs, all work-performing statements in AIT are in the form of function calls that are integrated seamlessly into the expression parser. Expressions are essentially the same as most other languages, though notably absent are bitwise operators (which must be done with functions and are limited to 32-bit integers). This is a relatively minor omission, though, and in every other way expression and function handling in AIT is clean and just simply works.
AutoHotKey seems to be more rooted in its language past than AIT does. Work-performing statements are a complex and somewhat bewilderingly arbitrary mix of commands and functions. And more bewildering is the fact that some statements work with expressions as arguments, and some don't. For those that don't, you need special syntax to use variables. For those that do, the method of using variables is different. It sometimes feels more like a macro-expansion at times than a scripting language. And the split between commands and functions isn't where it is for most languages where there is a split. Most languages with discreet commands separate from functions differentiate between them in that commands don't return a value and functions do. Thus, any time you have something that returns a value, you can incorporate it into an expression. However AHK isn't like that. Many things that return values are incorporated as a command, like PixelGetColor, where you supply a variable that the command will dump its result into as one of the arguments to the command. This makes it a good thing that you don't have to pre-declare variables in AHK. It also makes it very tempting to either use a lot of throw-away variables just to get that result you wanted into an expression, or start doing things like naming variables "Temp1" or "Temp2" just so you're not wasting 50 one-time-use variables. Either way, it leads to bad code that is either unreadable or bloated. One advantage (though this is likely contentious) that the AHK language has over AIT is with its block handling. It uses simple braces { } rather than discreet and arbitrarily named block starts and ends. Having read the AHK documentation where they call it the "one true brace style" leads me to believe this was a very deliberate change on the part of AHK developers early on. Now, while I too prefer braces, I won't go so far as calling { and } the "one true brace" - I like Pascal's "begin/end" just fine too. They both make for readable code in that all blocks have a consistent start and end. Of particular note to me is the way an if/else is blocked. I like this:
Code: Select all
if (test = true) {
; stuff
} ; if (test = true) <-- end of if
else { ; if (test != true) <--- beginning of else
; different stuff
} ; else if (test != true)
Code: Select all
if (CurrentRow != 1) {
PixelGetColor Row1Pixel, PixelX-4, Row1Y
if (Row1Pixel > 0x100000) {
MouseY := Row1Y
NewRow := 1
} ; if (Row1Pixel > 0x100000)
} ; if (CurrentRow != 1)
else { ; if (CurrentRow = 1)
Code: Select all
if (Blue($Pixel1) <= 0xd0 or Blue($Pixel2) >= 0x08) then
; stuff
;endif (did not find game window fingerprint pixels) <--- ghost line for documentation purposes
else ; if (we did find the fingerprint pixels) then
; other stuff
endif ; if (we did find the fingerprint pixels)
Screen/Graphics Support
By this I mean support for reading graphics from the screen. This is important to many people who use AHK or AIT to interface with games or other windows objects. Support for this is much the same for both AHK and AIT (PixelGetColor, PixelSearch in both) with one notable exclusive feature for each.
AIT supports a PixelChecksum function that creates a checksum for a region on the screen so you can determine if/when it changes. You create a baseline checksum, then can check it periodically to see if there are any changes. Lots of gaming potential for this gem. In the real world, I would have used this in the bot I wrote to test both AHK/AIT, but I also needed to test performance and didn't want the performance test to include anything exclusive.
AHK supports an ImageSearch command that looks at the screen and searches it for an occurrence of an image you specify. Fantastically handy for interfacing with games when you are looking for a graphical element that can change location and where you need to interface with it. It would be even better if you didn't have to have an image file for each image you wanted to search for. Small graphical elements you could include right in your script would be great.
Hotkey Support
Hotkeys, unsurprisingly, are AHK's forte. Hotkeys are handled by a special hotkey syntax that makes it very easy to make anything from a simple macro, to complex multi-step scenarios. Context-sensitive hotkeys controlled by directive-like statements are fairly easy to make as well. Putting together a complete helper package for a game is relatively simple in AHK. When you get into simulated threads and hotkey priorities, things begin to get complicated, but it is a complication born of being, if it's even possible, overly flexible. Add to the mix a flexible timer handler that can operate in either one-shot or multistable mode, and there really is not much you can't accomplish in AHK when it comes to responding to either user or software. Want an annoying pop-up window closed automatically any time it appears, no sweat. Want to replace a mouse click with a complicated maneuver with moves timed in a way no human can achieve, no sweat.
AIT's hotkey handling is simpler, almost an afterthought. AIT handles hotkeys through a hook function. You register your hotkey and the function that will handle it. This isn't a drawback, per se, but it does make it a little clunky if you use a lot of simple hotkeys where you just want a "hit a key, send some stuff" response. Multiple hotkeys can be registered to the same function in AIT and differentiated by the script. So AIT is flexible too in its own way, but constricting in that there is only one thread in any one AIT script. In one limited context, this is an advantage. I scripts that tend to use a common key to turn them on or off. I find the fact that there is a single thread in some cases an advantage, because wherever the script is in its execution, as soon as I hit the hotkey to turn it off, flow gets redirected to the beginning again. In AHK, I require a global "stop" flag I have to check at multiple places throughout the script to accomplish the same thing. This, however, is a complication born, as I said, of being if anything overflexible, and should not be taken as a design flaw in AHK. Just one way where AIT's limitations present a unique opportunity that happens to match my own scripting needs.
Performance
Performance between AIT and AHK is comparible. There is no really significant difference between the two other than in graphic handling. In that, PixelSearch and PixelGetColor are both notably slower in AHK vs AIT. It should be mentioned that AHK's fast version of PixelSearch was not used due to the fact that it's search direction (top down in columns) was not compatible with the needs of the script I wrote.
The testing I performed was a real-world MMO mini-game playing bot. The mini-game is to "catch" things coming at you in four different rows, moving the mouse from row to row to catch an item. A common little game. PixelSearch was used to determine the starting row, and polling with PixelGetColor in the three other rows was used to determine the row to move to thereafter. When I benchmarked the AHK and AIT versions of the script, I found AHK was able to poll about 4.5 times per second. AIT had performance a little over double this, at about 10 polls per second. This comparison, though, was almost entirely dependent on the performance of PixelGetColor (which is horribly slow on both). When PixelGetColor was removed, both loops ran at speeds which were comparible. Which means, for all intents and purposes, scripting is parsed about as fast as you need it to be in either AHK or AIT. Why PixelGetColor is so slow in both I don't know. Why it's twice as slow in AHK vs. AIT I also don't know. I don't have AIT's source code, and in AHK it is simply a call to the Windows API GetDC() and GetPixel() functions.
License
This is where a merry war could start, but even a discussion based solely on technical merits deserve mention of the license. As everyone I'm sure knows, AHK is GPL-based, while AIT is free-as-in-beer to use with claims that those who are committed to the project are allowed to contribute. A forum post on AIT's forums claimed that a limited source would be publicly available, but from what I can tell, this has not actually been the case for some time and I see no evidence of publicly available source code under any license for AIT. I'm not going to argue the philosophical merits. From a technical perspective, I will note that when I had an issue with performance of one specific function in AHK (PixelGetColor), I was immediately able to grab the source and see how AHK was doing it. I can't do that for AIT. So from a technical standpoint, AHK is vastly superior in this area. I can see exactly what it's doing and how. For a scripting language, where those that use it have to be at least technically savvy enough to write a script, the target demographic would benefit from source code.
Summary
The reason to use each will, because of their individual strengths and weaknesses, will necessarily be different. If you are writing a bot that requires complex AI or which is using screen pixel tests extensively, then AutoIt with its snappier graphical response time and more programmer-friendly language may be your choice. If you are using hotkeys a lot or need auto-timed polling, then AHK will be your bet. If you are doing something in between, then it's less clear. However, AHK is committed to being open source, and this is a transparent method that is both a community and technically friendly solution that cannot be ignored.
[EDIT]
13 Feb 2016 - Original version
14 Feb 2016 - Added text on compiling in "Development Environment" section. Revised "Performance" since I am unable to produce a rigorously comparable benchmark. Corrected minor grammar issues throughout.
16 Feb 2016 - Added a little blurb on the custom SciTE version available for AHK, and made a few other minor grammar changes.