只是扩展了 Julia 的回答,因为我不得不重新启动我的应用程序而不是更新,所以我研究了 Sparkle 是如何做到的 -
Sparkle 的最新版本(截至 11/2011)有一个名为 finish_installation.app 的项目目标,它包含在 Sparkle 框架的 Resources 目录中。 Sparkle 作为宿主 App 的一部分运行,将 finish_application 复制到 application_support 目录并使用 launch 来运行其二进制可执行文件,如下所示,传入宿主进程 ID 和重新启动路径:
NSString *relaunchToolPath = [NSString stringWithFormat:@"%@/finish_installation.app/Contents/MacOS/finish_installation", tempDir];
[NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil]];
[NSApp terminate:self];
好像有了这个函数,当父进程退出时(?),finish_application的父进程启动。
finish_installation 等待传入的进程 id 消失,还有一个初始检查以查看它的父进程是否已启动 (pid=1)
if(getppid() == 1)...
if (GetProcessForPID(parentprocessid, &psn) == procNotFound)...
然后启动应用程序:
[[NSWorkspace sharedWorkspace] openFile: appPath];
最后一个有趣的花絮:如果安装需要很长时间,finish_installation 会将自身更改为前台进程,以便用户可以看到某个应用正在运行:
ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType( &psn, kProcessTransformToForegroundApplication );