AppleScript, Catalina & Xojo made Mac Apps
Every once in a while I see someone posting about troubles with Apple Script, so I thought I'd try to help.
Friday, October 2, 2020 - Sam Rowlands
An updated version of this article for App Wrapper 4 is available from here.
In the golden days of the macOS, AppleScript was an important part of what made the Mac a Mac. I remember some crazy stuff we did with AppleScript, that would be considered mind blowing even today. You could empower and build upon apps made by other companies, making them do things that not even the original developers had thought of.
The good news is that AppleScript still exists and with the right combinations of set-up it's still useable for certain things.
If you're intending to ship an application on the Mac App Store, I would strongly advise you consider alternative technologies to accomplish the task, as the App Sandbox and App Store Rules make this even harder, and in some cases simply not allowed.
Lets get started
- Code sign your application with the harden runtime option. You can use App Wrapper to do this, version 3 of App Wrapper has support for IDE scripts, which will enable this for every debug run.
- Make sure you set a "Usage" message for Apple events. You can only set one message, which governs all the apps that you may be scripting. In App Wrapper 3, this is on the "Privacy" pane.
- Make sure that you are suppling entitlements when signing your application, as you need to set the "Apple Events" entitlement. In AW3 these options are on the "Capabilities" pane, if you're not targeting the Mac App Store and not using the App Sandbox, change the "App Sandbox" option to "Entitlements Only". If you're targeting the App Store or App Sandbox, read the section below AppleScript & App Sandbox.
- To execute AppleScript, I used my own "NSAppleScript" object (which is part of the Ohanaware App Kit, but you can use the one in the MBS plugin.
- When you run your signed application and attempt to execute the AppleScript, you should be presented with a dialog asking for permission. This dialog will appear every single time you run a new debug build or regular build.
- Handle the error. If the user clicks on "Don't Allow" an error will be returned to your application, and the user will never be asked again for that version of the application. Once you've handled the error, you can notify the user how they can enable this functionality again. An example is below.
if NSObjectIsKindOfClass( error, NSDictionaryClass ) then
// --- Grab the error number.
Dim errorCode as integer = XojoValue( NSObjectValueForKey( error, "NSAppleScriptErrorNumber" ) )
if errorcode = -1743 then
MsgBox "This application is not approved to do some Apple script with the current target." + endOfLine + endOfLine + _
"Please approve it, by selecting the target checkbox in the ""Automation"" section of the ""Privacy"" tab on the " + _
"""Security & Privacy"" Preference pane, within the System Preferences."
showURL "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation"
end if
end if
AppleScript & App Sandbox
The App Sandbox is a good idea, honestly, I actually like the App Sandbox principle. I do have a problem with it's implementation, and lack of response from Apple in attempting to get additional functionality added. The App Sandbox requires additional entitlements before your application can control others via AppleScript.
There are two entitlements for the App Sandbox, which will allow your application to communicate with others.
- Scripting Groups is the modern entitlement. This is the one that the App Store will allow, but it has very little support, take Apple Mail for instance, it only (currently) allows for generation of an e-mail, which can also be done via NSSharingServices or even using an mailto url.
- Temporary Apple Events is very difficult to get approval for on the App Store, the most likely outcome is that you'll be forced to remove all AppleScript support from your application. You can however use this entitlement with a non-App Store application as it allows your application to utilize all AppleScript functions from the target application.
In summary if you're looking to ship an application on the Apple Mac App Store, be prepared to remove the ability to control other apps via AppleScript.