I am trying to execute an Automator workflow from a sandboxed AppKit app.
Minimal example + github repo :
NSOpenPanel * panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setAllowedFileTypes:[NSArray arrayWithObject: @"com.apple.automator-workflow"]];
NSInteger result = [panel runModal];
if (result == NSFileHandlingPanelOKButton) {
NSURL * workflow = [[panel URLs]objectAtIndex:0];
NSLog(@"selected url %@", workflow);
NSError * error = nil;
[AMWorkflow runWorkflowAtURL:workflow withInput:[NSArray arrayWithObject:workflow] error:&error];
if(error) {
NSLog(@"Error while executing workflow %@", [error localizedDescription]);
}
}
From my current understanding of the AMWorkflow API I assume it uses Mach IPC to execute the workflow in a separate Automator Runner process.
This is why I added the following entitlement to my app:
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<array>
<string>com.apple.AutomatorRunner</string>
<string>com.apple.Automator</string>
</array>
But apparently Automator Runner tries to connect back to the calling app which fails with the following error msg:
Automator Runner(2717) deny mach-lookup /Users/pbrc/Library/Developer/Xcode/DerivedData/AMWorkflowCaller-arjgkslqihljquelyvybmpsnljrn/Build/Products/Debug/AMWorkf
0 libsystem_kernel.dylib 0x00007fff96ce9686 mach_msg_trap + 10
1 liblaunch.dylib 0x00007fff8db637c4
2 liblaunch.dylib 0x00007fff8db624d9 bootstrap_look_up3 + 69
3 liblaunch.dylib 0x00007fff8db62609 bootstrap_look_up2 + 40
4 Foundation 0x00007fff8f4acffe -[NSMachBootstrapServer portForName:options:] + 102
5 Foundation 0x00007fff8f4b84cb +[NSConnection connectionWithRegisteredName:host:usingNameServer:] + 30
6 Automator Runner 0x0000000100001a51 -[AMRunnerDelegate processArguments] + 487
Any ideas?
The simple answer is that the AMWorkflow API does not work in sandboxed applications. There is an alternative API which has been introduced recently, which works with sandboxed applications:
NSUserAutomatorTask executeWithInput:completionHandler:
Using this API you can execute automator scripts that are located in the script folder of your application:
/Users/USERNAME/Library/Application Scripts/BUNDLENAME.APPNAME
There is one significant caveat: Despite the method's "input" argument no input will be passed through to the automator workflow on versions of Mac OS prior to 10.8.3 12D75 (this is/was a bug):
NSUserAutomatorTask * task = [[NSUserAutomatorTask alloc] initWithURL:workflow error:&error];
if(error) {
NSLog(@"Error while creating script task %@", [error localizedDescription]);
}
[task executeWithInput: @"this will never reach your workflow" completionHandler:^(id result, NSError *error){
if(error)
NSLog(@"Error while executing workflow %@", [error localizedDescription]);
}];