Skip to content

Process()

This is a short post showing how to run an executable shell script from a Mac app.

The core API we’ll use is well known as NSTask recently transitioned to Process.

The docs describe an NSTask like so:

Using the NSTask class, your program can run another program as a subprocess and can monitor that program’s execution. An NSTask object creates a separate executable entity; it differs from NSThread in that it does not share memory space with the process that creates it.

So lets say you have a shell script called test.sh and you want to run it from a mac application. I’ll first put a possible version of the code that can run the script here:

I’ve put the code above in a String extension. Given the path to the script test “/Users/me/Desktop/test.sh” I can then call that function on that string and get the script executed.

So let’s briefly look at Pipe and Process.

Pipe:
It is defined as an NSObject:

In terminal we can use the pipe operator “|” to connect the standard output of a program to the standard input of another.

The reason why we’re using a Pipe here is to be able to direct the output of what the Process will run to handlers that will in turn allow us to drive UI that can provide feedback during the execution of the task.

So then we have two handlers, one for reading and one for writing. In this example we simply use the read.

Process:
The task is instantiated using Process() and we then setup its launchPath and configure needed arguments. The “arguments” of the Process object is there to allow us to specify the command arguments that should be used to launch the executable. In our case we will simply put the path to the shell script.
It is important to note that a Process can only be launched once, if you need to run the same task again then a new Process must be created first.

Conclusion

Using this pattern you can run executable shell scripts from a Mac app. In my case I’ve enabled the user to pick the path using an NSOpenPanel object, then calling “runAsCommand” on the url.path of the NSOpenPanel triggers the selected shell script. It is very useful to then use the handlers provided in the runAsCommand function call to update for example an NSTextView and get a very similar experience within a native Mac app like what you see when running the shell script in terminal.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *