Mac vs Windows Automation

I was always curious how Windows compares to Mac as far as automation goes.

From my experience, most interactions force you to interact with GUI elements and not do things through hotkeys which I think is quite bad.

Really? I find that very surprising. AFAIK, there is no Windows equivalent for:

  • AppleScript
  • Keyboard Maestro

But then it's been years since I was regularly using Windows.
Have I missed something?

I was always curious how Windows compares to Mac as far as automation goes.

From my experience, most interactions force you to interact with GUI elements and not do things through hotkeys which I think is quite bad.

Well I mean it really depends... Largely it depends on whether you are good at coding or not. I have spent the last 3 years learning how to automate windows applications. Many times I thought I had reached the pinnacle of automation on the OS. Then something else came along which completely blew what I once thought I knew out of the window. Though each level up I went I had to learn more about how Windows OS works, new programming techniques etc.

and not do things through hotkeys

Most windows software has mnemonics. For example, tapping Alt then H in excel and I get this:
https://puu.sh/x8HnN/cebfe7337f.png
now when I press any of the above keys that function is executed. So... Alt-H-1 makes text bold

Some windows software aren't as fancy and don't have a ribbon but mnemonics are still around:
https://puu.sh/x8Hth/d9691f4fe9.png
That is what happens when you press alt-f in notepad++. Here letters which are underlined are the mnemonic. So pressing Alt-F-E will save all the files in notepad++ etc.

So windows does heavily rely on keyboard shortcuts. One thing that is really nice is the ability to know where the cursor (not just the mouse) is AND the ability to 'right click' on the cursor's location (not just at the mouse location). This is something which is impossible on Mac. There are some options here using Voiceover but nothing consistent.

@JMichaelTX It must have been a very long time since you used windows then :stuck_out_tongue:

Equivalent of AppleScript

Actually there are many things that one can use which have all the powers of Applescript (and more) all natively on windows. VBScript, JavaScript (a.k.a JScript released at the same time and has feature parity with VBScript) and recently Powershell.

Equivalent of Keyboard Maestro

I mean there are loads, but unlike KM they are mostly 'keyboard-typed' programming languages not visual programming languages. There is AutoIt, which was first released in 1999 (before even KM), and the language that I use most for windows automation, Autohotkey which is a free, open source and really powerful automation solution. Lua-Macros is another I have heard a lot about. It's been around since 2004 so, I'd be very surprised if you haven't heard of it before...


As far as Native Windows automation technologies go:

  • Windows Messages API (includes event based programming)
  • Win32 API
  • COM OLE API
  • Active X Controls
  • MS Active Accessibility API (includes event based programming)
  • UI Automation API (includes event based programming)
  • DLL Injection (This is major but does require a lot of C/C++ knowledge)
  • The .NET API (And most importantly the CLR API, allowing you to dynamically execute VB.NET and C#.NET code from any COM compatible language).

But then there's also security. In general Windows machines are very 'open'. For example anything can modify the registry on the system, and if you screw up your registry, it's game over. You don't have to 'enable accessibility' on certain applications on windows, any application by default has complete control over your mouse, keyboard etc. Bots can be made which identify your passwords etc. All these things are virtually impossible on a Mac, which is why Mac's are a really safe option.

However, from an automation point of view, Windows OS is much better. It works out of the box, and we have full access to everything on the system, from the moment of conception of your script. The main trick of the trade is knowing when you need to be cautious, and what you shouldn't do on your system.

If I were to choose between the 2 systems, Mac and Windows, I doubt I could. They are both so good at different things. It's better you use the system exclusively for what it's good at, in my opinion. (Unless you want a challenge of course ;))

1 Like

Again, that surprises me. One of the Mac apps that I use AppleScript a lot to automate is Evernote.
There is also an Evernote app for Windows, and in spite of numerous requests, I have never seen anyone provide scripts comparable to EN Mac AppleScripts to automate EN Win. Do you know of a scripting language that could automate EN Windows?

Do you know of a scripting language that could automate EN Windows?

Autohotkey (AHK) would definitely be able to, but to what extent? I am unsure. Sadly it seems I am not able to download the application to experiment with it. It looks like it's built in electron (chromium based), and if so acc.ahk is the answer (an AHK library a lot like the UI Elements object in Applescript).

Though, in general when it comes to electron, it is far better to decompile and edit the source :stuck_out_tongue: Though that's probably against the license terms...

AHK and AppleScript are oranges and apples. :wink:

As far as I can tell, AHK can only communicate with an app via the apps UI. That is certainly useful, but limited.

OTOH, AppleScript actually communicates directly with the app executable, and is able to get and set app data, some of which may not be available via the app UI.

Here is an example of an AppleScript I'm working on now to automate the identification and tagging of duplicate Notes. It does the following without ever using the Evernote UI:

  • Gets the Title, Created Date, and Note link into arrays for all Notes
  • Using ASObjC (AppleScript Objective-C), sort the data with 3 levels (not possible in the UI)
  • Using ASObjC, very quickly identifes dup Note titles
    • It takes only 0.3 sec to identify 300 dup sets out of 18,000 Notes
  • For each of the dup Note sets, add an Evernote tag to each Note, identifying it as a dup.
  • The user can then, via the normal EN UI, filter the Note list by the dup tag, and take further action, if needed

Complex AppleScripts have been written to do many things, including the migration of data from one app to another, often involving 10s of thousands of records.

I don't see AHK, or any other Windows automation tool, doing anything like the above.

I see you're talking about scriptable applications, i.e. AppleEvents, here. The equivalent of AppleEvents in Windows is the IDispatch interface. Many applications implement them although I can't say the same for EverNote. If EverNote doesn't implement an IDispatch interface but does implement an AppleScript interface, then that's the application vendor's decision. Similar case can be said the other way round, and it doesn't make one OS better than the other in that regard. Having tried to implement both AppleEvents and an IDispatch interface in my own applications, I can tell you which is easier to implement... And it's similarly why there are so few scriptable applications out there...

Note: The IDispatch interface, or indeed AppleEvents, are not the only ways an API can be implemented. Windows natively has 5 methods which are accessible in the majority of scripting languages: Clipboard, COM, Windows Messages, DDE, File Mapping, Mailslots, Pipes, RPC, Windows Sockets (See details). AppleScript has: Pasteboard, AppleEvents, Pipes (barely), Distributed Notifications (visible), RPC (See details). Which one the application developer chooses to use is up to them!

Here's some code I wrote to, for example, extract an entire staff list from our company's exchange server using AHK:

#SingleInstance, Force
#Include libs\JSON.ahk
Employees := getPEEmployeeInformation()
FileAppend, % "Count: " . Employees.length(), Employees.JSON
FileAppend, % JSON.stringify(Employees), Employees.JSON
Msgbox, All done!
return


getPEEmployeeInformation(){
    Employees := []
    Application := ComObjCreate("Outlook.Application")
    myNameSpace := Application.GetNamespace("MAPI")
    contacts := myNameSpace.AddressLists("Global Address List")
    For contact in contacts.AddressEntries
    {
         if contact.AddressEntryUserType=0 {
             oExUser := contact.GetExchangeUser()
           
             if oExUser.JobTitle <> "" {
                 Alias   := lCase(oExUser.Alias)
                 FirstName  := oExUser.FirstName
                 LastName  := oExUser.LastName
                 OfficeLocation := oExUser.OfficeLocation
                 Email   := oExUser.PrimarySmtpAddress
                 JobTitle  := oExUser.JobTitle
                 Department  := oExUser.Department
                 Street   := oExUser.StreetAddress
                 City   := oExUser.City
                 PostCode  := oExUser.PostalCode
                 Telephone  := oExUser.BusinessTelephoneNumber
                 ContactID  := oExUser.ID
                 ManagerID  := oExUser.Manager ? oExUser.Manager.ID : ""
                 EmployeePhoto  = https://amazing.url/User`%20Photos/Profile`%20Pictures/%alias%_LThumb.jpg
                 Employees.push({"Alias":Alias,"FirstName":FirstName,"LastName":LastName,"OfficeLocation":OfficeLocation,"Email":Email,"JobTitle":JobTitle,"Department":Department,"Street":Street,"City":City,"PostCode":PostCode,"Telephone":Telephone,"ContactID":ContactID,"ManagerID":ManagerID,"EmployeePhoto":EmployeePhoto})
             }
         }
     }
     return Employees
}

lcase(s){
    StringLower, OutputVar, s
    return OutputVar
}

I guess this is somewhat akin to your own EverNote example.

I wouldn't talk to me about speed :wink: For a start AppleScript, I'm pretty certain, is much slower than AHK. But not just that, but you're talking about ASObjC algorithms, which is great and all, but compared to compiled code that is very slow... Fortunately for the likes of AHK, we can run compiled machine code directly using the Win32 API, which as you may know, is as fast as you can get. There is nothing faster than machine code... In fact I have been donating to the MCode project (which is all about compiling machine code and using it within AHK).

I was browsing online, as you appeared to suggest that EverNote uses some sort of database. Turns out it's actually a SQLite database. So you can work directly with the database and bypass their API entirely using the SQLite.dll. Again, it's probably faster than using the AppleEvents library, because the calls are made directly to the compiled binary. Adding the EverNote tags though, I'm not sure about. But I can say that it is completely possible to do. In general, applications are just state machines, they react on their inputs. Emulate their inputs, find out what changes, and you can do anything.

So in summary, the AppleEvents API is great, but it's very difficult to say that one is any faster and/or flexible than the other unless you have been there and worked extensively with both systems. I have invested a lot of time in trying to find equivalent technologies on Mac to those in Windows, but since Mac sandboxes every application (due to the unix core) many advanced techniques become virtually impossible to replace in any stable manner.

P.S. I am not saying that there are no features on a Mac OS which I like. All methods from the Objective C Runtime library are absolutely delicious when it comes to automation. Which is one of the advantages of software developed in Objective-C... You can have a whale of a time with .framework injection with those Objective C methods... Sadly there is nothing of the sort on Windows. Or at least, not that I know of (yet).

P.S.S. When it comes to EverNote you may be right that AppleEvents is the easiest method of automating the application, and from one perspective that also implies it is the best. But if an application is really that unfriendly to Windows users who want automation... Why would they use it in the first place? In such cases, one would likely be better off sticking with the application Microsoft built which of course has a COM and DDE API or open source alternatives.

Edit: Just found that EverNote does actually have a COM API, so that'd be an official way of accessing the EverNote instance. So in AHK, ComObjCreate("ENSessionCOM").SetSharedSessionConsumerKey("your key", "your secret"). It is a cloud API though.

Anyway, I fear this is a little off topic :stuck_out_tongue: Might want to split the conversation to another thread...

Thanks for sharing that. Your code clearly shows the app scripting power of AHK, which I had not seen elsewhere. Didn't see anything like that on the AHK web site.

Your code reminds me a lot of JavaScript for Automation (JXA), which is a sister to AppleScript and also based on Apple Events, but uses the core JavaScript engine.

No doubt that compiled code is faster, but I have to say that when I can search 18,000 for dups in only 0.3 sec using ASObjC, that is fast enough for me.

But even native AppleScript can be very fast. For example, we developed a script that searches 10 windows and 200 tabs of Chrome (or Safari) to find and open the window/tab of a given URL, in only 0.14 sec.

Good point, and I certainly have no recent experience in Windows. I think what caught my attention is that you moved from Mac to Windows because of automation. I had not see anyone previously making a platform choice for that reason.

Thanks for sharing your experience.

You're right. I'll split our discussion to a new topic now.

[quote="JMichaelTX, post:8, topic:7658"]
Your code reminds me a lot of JavaScript for Automation (JXA), which is a sister to AppleScript and also based on Apple Events, but uses the core JavaScript engine.[/quote]

Yes, the JavaScript engine is written in C++ and was heavily influenced by C++. Similarly AHK is written and heavily influenced by C++. AHKv1, however, is heavily influenced by Batch. So that's what, in general, gives AHK a really really weird syntax... Then again JXA-ObjC has odd syntax also... xD I do prefer JXA to AS at least :stuck_out_tongue:

[quote="JMichaelTX, post:8, topic:7658"]
No doubt that compiled code is faster, but I have to say that when I can search 18,000 for dups in only 0.3 sec using ASObjC, that is fast enough for me.

But even native AppleScript can be very fast. For example, we developed a script that searches 10 windows and 200 tabs of Chrome (or Safari) to find and open the window/tab of a given URL, in only 0.14 sec.[/quote]

Fair enough. If I remember correctly, I have done duplicate searches 30,000 records using SQL engines and it takes roughly 3ms, if I remember correctly. But I can't remember totally, it was 2.5 years ago now :stuck_out_tongue:

One of the things I am sad about is Chrome's lack of an iDispatch interface (or similar). It has an AppleEvents API, so I do find it odd how it doesn't implement an IDispatch... So most automated web applications use IE (or have to implement Chromium - Normally only lower level languages). There are those who have gotten the active tab's URL from Chrome in AHK. I would assume extending it to finding a tab is trivial, as it uses ACC.AHK, but I would need to check how fast it is myself.

Well it's not like I don't use my Mac... I'm using my Mac now, while being on the internet. I am trying to keep my Windows PC clean as that effects performance, so I use my Mac's for entertainment and browsing the web, and the Windows PC for programming and automation :stuck_out_tongue: It's an odd world I live in :stuck_out_tongue: