OS X: Launching Another Application Programmatically

Share Button

Occasionally an application may require that another application be run. This other application may be some behind-the-scenes “helper” or auxiliary app, or it may be necessary for the user as part of a larger workflow. In this post, we go over some techniques for launching an application programmatically. In the process, I’ll go over a general method for passing parameters to a bundled AppleScript.

An Xcode project for this is available on github.

A Very Simple Approach
The Wrong Way To Do This

For the simplest situations — where you simply want to get another app to launch and become the frontmost app — it’s possible to write just a few lines of code that leverages AppleScript. Here’s a basic function:

This is a two-step process: we have to run the app, and then activate it. If we simply activate, an already-running app will become the frontmost app; however, if the app is not running, it will launch as desired, but not become the frontmost app. We could get around this by simply doing the activate twice, but in the case of a running app, this tends to produce a “flash”.

The osascript shell command simply executes AppleScripts, so we construct our script with the appropriate code, and then use the system call to execute it. So we have a chain of execution here: our app executes the system function, which calls osascript, which then executes the AppleScript code. The plethora of backslashes are a bit jarring to the eye, but are necessary to produce the correct C string to pass through each layer of this onion-like execution path.

Another Simple Approach (Also Wrong)

Because we’re using AppleScript in the approach taken above, it may occur to you that we could simply write a separate AppleScript, and use the system call to execute it:

The problem with this is that MyScript.scpt needs to be on the path that system uses. Definitely can be done in some ad-hoc fashion, or the the full path can be provided; but this is no argument in favor of this approach.

The Right Way

Astute readers will object that this (a) is pretty ugly, and (b) does not leverage built-in Objective-C/Cocoa functionality at all. This is quite true, and I only show it in case straight C code is the only alternative, and for pedagogical reasons. Here’s the same approach, done much more “correctly”:

Here, we’re doing exactly analogous steps to the “wrong way”, but it’s clearly more in the spirit of programming for OS X. Another advantage to this approach is that we can get informative result/status back from the attempt to execute the script code (see this stackoverflow post for an example); in contrast, the system call only returns an error code.

Using a Bundled AppleScript
Hard-Coded Script

Perhaps the “best practice” approach to the problem noted above is to include the script in the app’s bundle, and to use NSAppleScript. I’ll present the simpler version of this first, in which the script itself hard-codes the name of the app to be launched. The idea is simple: we can create an NSAppleScript directly from the bundled script, and execute it as in the second example listed:

The bundled script is simple:

For such a trivial task as launching an application, creating a bundled script offers little advantage over the construction-on-the-fly nature of the previous approach. However, in the case of more complex script code, keeping the script as a separate file will make for cleaner code, and allow for development and debugging of the script to be done in a more standalone fashion.

 Passing Parameters to An AppleScript

The preceding example is simple, and works fine if there’s only one app you’ll be needing to launch. However, it is possible to create an AppleScript that contains a parameterized function, and to call that function with an argument (in our case, the name of the app to be launched). Such a script might look like this:

The code to create the NSAppleScript object and to create the parameter-argument pair comes from some Apple documentation addressing the passing of parameters to scripts in general:

This is rather a lot of code, consisting primarily of the commands that set up the parameter passing. Apple’s comments describe the role of the various objects/functions involved, so I won’t go into details.

This approach is probably massive overkill for our purpose, but I’ve included it to show how to pass parameters from an app to an AppleScript it executes. More parameters can be passed — note that the code uses a list-type event descriptor:

The code block following  if (scriptObject != nil) {  can be generalized, then, to create and pass a number of parameters to the script. Such additional parameters may be used directly as part of AppleScript commands, or may be themselves passed as parameters to the application that gets launched by the script.

The Apple technical note I referenced contains details on how to bundle an AppleScript using Xcode, as well.