3

SMJobBless()简短版本:删除应用程序时是否可以删除应用程序(等)设置的帮助工具?如果是这样,怎么做?

长版:

不幸的是,我们正在开发的 Mac 应用程序需要管理员权限才能执行偶尔的操作,并且即使应用程序本身没有运行,它也需要后台任务才能连接到其他应用程序的插件(这个可以是非特权的) . 该应用程序将使用 Developer ID 证书进行签名,并且仅在 App Store 之外分发。

我们希望该应用程序尽可能成为“好公民”,即使在卸载时也是如此。

对于后台任务,我们使用了一个登录项,使用SMLoginItemSetEnabled(). 这并不令人惊讶,因为 XPC 消息传递似乎不起作用(我们正在使用CFMessagePort- 欢迎替代建议),但如果用户删除应用程序,登录项至少在下次登录时不再加载。我怀疑系统中的某个地方仍然存在它的痕迹,但是使用了 .app 包中的可执行文件,当它消失时,登录项不再运行。

对于偶尔需要管理员权限的操作,我们有一个特权帮助工具,我们的应用程序使用它安装SMJobBless(),它实现了一个命名的 XPC 服务,因此当它收到来自主应用程序的消息时,任务会按需启动。这是 Apple 在其Even Better Authorization Sample中推荐和描述的内容。

助手可执行文件被复制到/Library/PrivilegedHelperTools/by SMJobBless(),嵌入的 launchd.plist 最终在/Library/LaunchDaemons/. 即使操作系统有关于哪个应用程序“拥有”助手的信息,但当用户删除应用程序时,它似乎并没有卸载它。Apple 的示例对卸载保持沉默,除了uninstall.sh显然仅打算在开发期间使用的脚本。当应用程序没有运行时,我们不需要这个帮助程序,所以将它安装为一个成熟的启动守护进程有点过分,但我们也想避免重复地用密码提示来烦扰用户。此外,Apple 建议不要使用其他形式的具有管理员权限的运行代码,SMJobBless()例如SMJobSubmit()标记为已弃用。

那么我们如何清理自己呢?

我找到SMJobRemove()了,但是(a)在我们的情况下,我们什么时候会调用它 - 你不能在 .app 包删除时运行代码,或者你可以吗?(b)它实际上似乎并没有清理干净

我能想到的唯一两件事并不是非常令人满意:

  1. 某种卸载程序或脚本。但这似乎也很丑陋。
  2. 不用担心,当用户删除我们的应用程序时留下一团糟。
4

4 回答 4

2

在https://forums.developer.apple.com/thread/66821的 Apple Developer Forums 上也有类似的问题- Apple 的建议是手动卸载机制,如果用户不这样做,则消耗尽可能少的资源做这个。

Apple DTS 工作人员进一步建议在特权启动守护程序中实施自卸载机制,以通过 XPC 从应用程序触发。这就是我们要做的。

于 2016-11-11T14:28:19.873 回答
1

您可以考虑的一种解决方案是在 .app 包中包含卸载程序脚本或程序。

然后,您可以将这个小工具的路径传递给您的帮助工具(通过 IPC)并让执行卸载程序,从而删除自身。您必须小心以正确的顺序移除组件,但可以使其正常工作。

于 2016-10-25T03:47:11.903 回答
0

我认为您现在唯一的解决方案是使用您提到的卸载 shell 代码,以便从磁盘物理删除特权助手或为其构建卸载程序。无论哪种方式,您都必须要求用户输入他/她的密码。这是所有需要对系统进行特权访问的安装程序/卸载程序所做的事情,并且有一个很好的理由。这就是为什么我避免像瘟疫一样使用特权助手,但我知道有时你真的必须这样做。我不认为你在用户系统中留下这样一个助手是不好的,因为它会在用户下次启动计算机时重新加载。

我刚刚检查了 ServiceManagement.h 标头,他们声明 SMJobRemove 将被将来通过 libxpc 提供的 API 取代。(有时您确实需要转到标题以获取文档未提供的额外信息。)希望这个承诺的替换将为我们卸载它。但是,我会提交错误报告并要求进行改进。

于 2016-10-11T22:44:39.230 回答
0

您是正确的,Apple 没有提供 API 来卸载安装的帮助工具,SMJobBless它们也不会自动这样做。至于为什么 macOS 不会自动进行卸载,我有根据的猜测是因为 macOS 从根本上没有统一的“安装”概念。虽然应用程序位于 /Applications(和其他一些位置)是惯例,但从系统上的任何位置(包括外部驱动器和网络驱动器)定位和运行应用程序是完全有效的。例如,当应用程序因为它们所在的驱动器断开连接而消失时,macOS 是否应该卸载帮助工具?

如何卸载而言,这样做需要root权限,因此实际上让帮助工具本身进行卸载是最简单的选择。您可以通过 XPC 让您的应用程序告诉助手自行卸载。这是Swift中的一个示例,说明如何执行此操作;它是SwiftAuthorizationSample的一部分。基本思想是:

  • 使用launchctl命令行工具卸载辅助工具
  • 删除辅助工具可执行文件
  • 删除辅助工具launchd plist

但是涉及一些额外的复杂性,因为launchctl不会让您卸载正在运行的进程。

于 2021-10-28T07:58:33.540 回答