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

Jav*_*rol 4 macos cocoa applescript objective-c 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];
Run Code Online (Sandbox Code Playgroud)

这非常有效,但我一直在阅读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];
Run Code Online (Sandbox Code Playgroud)

这仅在用户拥有应用程序时有效,否则,它将提示询问应用程序位置的对话框.(并在Dock中显示示例图标几毫秒)

我也一直在尝试一些更多的hacky解决方案,如:

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.");
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题是:

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

谢谢

NSG*_*God 7

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

NSURL *appURL = [[NSWorkspace sharedWorkspace] 
               URLForApplicationWithBundleIdentifier:@"com.example.test"];
Run Code Online (Sandbox Code Playgroud)

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

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