Programmatically enable (or disable) AppleScript support for an application

423 Views Asked by At

I have an App Store app in which the free version is not scriptable, but the premium version is. AppleScript support is one of the key differences. I know the App Store reviewers are pushing more and more towards free + in-app-purchase, which will help declutter the App Store. Fine, I'll play ball.

Now I need to do something programmatically that I've always just worked into the build.

  • Is there a way to disable AppleScript if my OSAScriptingDefinition and NSAppleScriptEnabled are set in my Info.plist? This would still allow people to open the dictionary, and maybe they'd like what they see and consider activating the upgrade. Or,

  • Is there a way to enable AppleScript after the fact? Obviously with code-signing, I can't do things like modify Info.plist, or add my SDEF to the bundle later. But maybe if the SDEF were in a non-standard location, I could load it from the bundle and tell the system about it manually.

Does the SDEF have to live in my bundle? If not, I'm not sure how to point to the user's Application Support directory in the sandbox. I've also considered xinclude an SDEF I can install after the fact, but again, the SDEF and plist require actual directory paths and not functions.

I've tried a couple of things such as attempting to set NSScriptSuiteRegistry's singleton to nil, to no effect.

Because OSAScriptingDefinition and NSAppleScriptEnabled enable "automatic" support, surely there must be a manual way to make them to effect if not in the plist, and hopefully with a public API.

Any ideas here? Thanks!

2

There are 2 best solutions below

9
On

A few points, for orientation:

  • All AppleScript commands are subclasses of NSScriptCommand
  • All AppleScript objects are represented by subclasses of NSScriptObjectSpecifier
  • The scriptability of an app is controlled by its shared instance of NSScriptSuiteRegistry

This gives you a few options. You could try, for instance, overriding NSScriptSuiteRegistry setSharedScriptSuiteRegistry: and setting it to nil for the free version. You could also write a category on NSScriptCommand and/or NSScriptObjectSpecifier that does a version check. That would give you fine-grained control: you could call it from any methods that handle a script command or returns a script object, and decide on the fly which you want to allow and which you want to block; maybe even pop up a 'Pay for Full AppleScript Access' dialog.

2
On

CocoaScripting is a black box and not very adaptable. Simplest (kludgy) solution would be to wait until CS has installed its Apple event handlers then call -[NSAppleEventManager setEventHandler:andSelector:forEventClass:andEventID:] to replace those with a dummy handler that always sends back a "requires in-app purchase" error. (Don’t replace the standard open, quit, etc. handlers obviously.)