这是使用 NSAppleScript 将参数传递到 AppleScript 处理程序的正确方法:
// load/compile AppleScript
NSAppleScript *scpt = [[NSAppleScript alloc] initWithSource:
@"on joinText(a, b)\n"
@" return a & b\n"
@"end addTo"];
NSString *arg1 = @"Hello ";
NSString *arg2 = @"World!";
// pack positional parameters
NSAppleEventDescriptor *params = [NSAppleEventDescriptor listDescriptor];
[params insertDescriptor: [NSAppleEventDescriptor descriptorWithString: arg1] atIndex: 1];
[params insertDescriptor: [NSAppleEventDescriptor descriptorWithString: arg2] atIndex: 2];
// build Apple event to invoke user-defined handler in script
NSAppleEventDescriptor *eventDesc = [NSAppleEventDescriptor appleEventWithEventClass: 'ascr'
eventID: 'psbr'
targetDescriptor: [NSAppleEventDescriptor nullDescriptor]
returnID: 0
transactionID: 0];
[eventDesc setDescriptor: params forKeyword: '----'];
[eventDesc setDescriptor: [NSAppleEventDescriptor descriptorWithString: @"joinText"] forKeyword: 'snam'];
// invoke handler
NSDictionary *errorInfo = nil;
NSAppleEventDescriptor *resultDesc = [scpt executeAppleEvent: eventDesc error: &errorInfo];
if (resultDesc)
NSLog(@"Result: %@\n", [resultDesc stringValue]);
else
NSLog(@"Error: %@\n", errorInfo);
这避免了即时编译和编译 AS 脚本的需要 - 正如您的原始 ObjC 代码所展示的那样,由于清理不足,这是在您的程序中引入错误和安全漏洞的丰富机会。
...
这是在 AppleScript 中组装 shell 脚本字符串的正确方法:
do shell script ("chown -R " & quoted form of username & " " & quoted form of filepath)
AppleScript 的do shell script
命令不提供传递参数的安全机制(它在许多其他方面也存在缺陷),但 AS 字符串具有quoted form
至少返回适合连接到 shell 脚本字符串的带引号和转义版本的文本的属性.
...
当然,通过do shell script
AppleScript 调用 shell 只是为了chmod
以升级的权限运行,这本身并不是一个小问题,尽管这主要是 Apple 的错,因为它没有提供简单的官方 API 来执行此操作(例如,通过添加“以管理员权限运行”选项到NSUserScriptTask
)。
Apple 确实提供了一个示例项目SMJobBless,它展示了如何使用服务管理框架和 launchd 添加和运行特权进程。但这是一个足够复杂的解决方案,很多人会(有意或无意地)偷工减料或完全做错事,这反而违背了首先提供安全做事方式的意义。但是您需要与 Apple 合作。