Search code examples
swiftmacosappstore-sandbox

How to call shell scripts to manage LaunchAgents from a sandboxed macOS application?


I have a non-sandboxed macOS application that happily calls on shell scripts in its resource bundle with the following approach:

class func runShell(launchPath: String, arguments: [String] = [], waitUntilExit: Bool) -> Void {
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    if waitUntilExit {
        task.waitUntilExit()
    }
}
ABCProcessManager.runShell(launchPath: scriptPath.path, arguments: ["-workingdirectory", path], waitUntilExit: true)

I'm trying to convert the application to a sandboxed one (for App Store upload) but it freezes when it calls the scripts.

The scripts manage a launchagent. Loading, unloading, starting, stopping.

How do I need to change my code to make it work with the sandbox turned on? Maybe there is a "sandboxed way" of managing launch agents?


Solution

  • I found an answer on Apple Support forums posted by an Apple staff member:

    Is is possible to have applications in the Mac App Store that work with LaunchAgents?

    No.

    Why not:

    1. XPC Services included within an app are only available to that app.
    2. Mac App Store apps are not allowed to include a launchd daemon or agent.

    They also mention that technically there is one undocumented way, but strongly recommend against going down that path:

    As an accident of the implementation, the service registered by a sandbox-compatible login item is visible to other processes running in the user’s session. So on current systems you could make this work by implementing a sandbox-compatible login item (as illustrated by the AppSandboxLoginItemXPCDemo sample code) and have your command-line tools talk to it. The problem with this approach is that it’s an accident of the implementation rather than a documented feature. Moreover, it runs counter to the general App Sandbox goal that a sandboxed app should be isolated from the rest of the system.

    So I guess I will be sticking with a non-sandboxed application distributed directly to customers.

    Apple support post link