在不破坏沙箱的情况下检查外部应用程序是否存在的代码

时间:2014-08-13 15:25:01

标签: objective-c macos cocoa applescript appstore-sandbox

我正在创建一个应用程序,我想检查我的计算机是否已经安装了一个应用程序(Example.app,com.example.test)并能够将该应用程序发送到Mac App Store。

我尝试了几件事,比如:

NSString *script = @"try\r tell application \"Finder\" to get application file id \"com.example.test\"\r set appExists to true\r on error\r set appExists to false\r end try";
NSAppleEventDescriptor *result = [self executeScript:script];
return [result booleanValue];

这非常有效,但我一直在阅读Apple在权利文件中不允许Finder的临时例外,以保证应用的安全。

我也尝试了类似的东西,但避免使用Finder:

NSString *script = @"set appID to id of application \"Example\"\r set msg to exists application id appID\r tell application \"Example\" to quit\r return msg";
NSAppleEventDescriptor *result = [self executeScript:script];
return [result booleanValue];

仅当用户拥有应用时才有效,如果没有,则会提示询问应用位置的对话框。 (并在Dock中显示示例图标几毫秒)

我也在尝试一些更为苛刻的解决方案,如:

NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/bash"];
[task setArguments:@[@"if ls /Applications/Example.app >/dev/null 2>&1; then echo FOUND; else echo NOT FOUND; fi"]];
[task launch];
[task waitUntilExit];

int status = [task terminationStatus];

if (status == 0)
    NSLog(@"Task succeeded.");
else
    NSLog(@"Task failed.");

但是任务总是失败,我认为命令行的东西永远不会工作(如果是这样的话,无意义的沙盒)。

我一直想放一个按钮(复选框),提示一个对话框以选择App的路径,并检查应用名称是否等于Example,如果是,请选中复选框,然后取消选中是否不是。但我不知道如何提示该对话框。 (如果有可能,我想避免这个解决方案)

我的问题是:

  • 是否可以根据沙盒规则知道应用程序是否存在(未打开)?
  • 我可以将Finder设置为临时例外,Apple会批准吗? (解释意图是什么)

由于

2 个答案:

答案 0 :(得分:7)

您是否使用NSWorkspace尝试了以下内容?:

NSURL *appURL = [[NSWorkspace sharedWorkspace] 
               URLForApplicationWithBundleIdentifier:@"com.example.test"];

如果结果为nil,您可以认为启动服务不是“了解”应用程序,无论它位于何处,否则它将返回NSURL。 (启动服务是CoreServices伞形框架的一部分,是处理应用程序和文档绑定的框架)。使用Launch Services通常比检查特定路径更好,因为app bundle可以在文件系统中移动但仍然存在。

您发布的AppleScript代码可能与Finder调用上面显示的代码相当:它只是调用Launch Services来查找具有该bundle标识符的应用程序。

答案 1 :(得分:0)

我认为(根据2012年WWDC的自动化会议),您应该使用NSUserScriptTask。确切地说,您需要子类NSUserAppleScriptTask,并且您能够在沙箱之外触发用户定义的AppleScript。它将使用XPC服务执行脚本,并使用命令行实用程序osascript运行脚本。您的应用程序是沙箱,因此可以安装脚本的唯一允许位置是NSApplicationScriptsDirectory,位于~/Library/Application Scripts/<bundle-id>/

请注意,默认情况下它不是自我定位的应用程序上下文,因此当您需要编写应用程序脚本时,您需要明确告诉应用程序执行操作。因此它不像NSAppleScript那样运行,它将由应用程序本身NSUserScriptTask执行,它的子类将在应用程序(沙箱)之外运行。