macos - 如何像 Finder 一样丢弃当前用户不拥有的项目?

标签 macos filesystems nsfilemanager nsworkspace

我正在编写一个工具,它提供了删除选定项目(文件、文件夹)的选项。通常,我会调用 -[NSFileManager trashItemAtURL:...]对于这些项目中的每一个,正如 this 中所解释的那样在 this所以问题。

但是,这些在尝试从其他用户拥有的目录中删除文件时不起作用,例如 root .在这种情况下,我的工具应提供与 Finder 相同的选项,即要求用户通过提供管理员用户的凭据来授权操作,然后我的应用程序会像 Finder 一样将项目移动到垃圾箱。

我已经尝试通过使用特权助手来解决这个问题,如 EvenBetterAuthorizationSample 的概述。示例代码,使用 launchd , SMJobBless和 XPC 服务。

然而,问题在于,特权助手以 root 用户身份运行,而不知道我的应用程序在当前用户下运行。结果是,当它删除一个文件时,它最终出现在根用户的垃圾文件夹中,而不是像 Finder 那样在用户的垃圾文件夹中。

我该如何解决这个问题,即 如何将不属于用户的项目移动到当前用户的垃圾箱而不是根用户的垃圾箱?

有什么技巧可以让我继续使用现有的垃圾回收功能之一吗?

因为 自己做这个 Action 不能正常工作放回 工作,垃圾的.DS_Store文件需要更新,并且没有 API,AFAIK。

最佳答案

我几乎找到了解决方案:

分析

当助手运行时,例如来自 launchd ,或通过AuthorizationExecuteWithPrivileges (在 macOS 10.15 下),它可能以 root 身份运行,不知道登录用户,因此它无法确定用户的垃圾文件夹。

奇怪的是,环境变量(见 man env )甚至可以显示当前用户的名字和主目录,但是真实的用户 ID,可以用 getuid() 查询。 , 将返回 0(根),这也会导致 NSUserName()NSHomeDirectory()返回root用户的信息。看来trashItemAtURL及相关功能依赖NSHomeDirectory()确定垃圾箱文件夹位置。

半成品解决方案

幸运的是,有一种方法可以更改真实用户 ID,使用 setreuid .

因此,在我的测试中,当我调用 setreuid (501, 0) (501 是当前登录用户的 uid),然后是 trashItemAtURL确实将文件移动到用户的垃圾箱文件夹,并在必要时自动重命名。

但是,这不会使 放回 工作,就像使用 Finder 删除同一个文件时一样。

使放回工作

看起来像 的原因放回 不工作来自更深层次的问题:它似乎是 macOS 框架中的一个长期存在的错误,请参阅 this bug report .

这基本上意味着:在 Apple 修复潜在错误之前,这是我们能从中得到的最好结果。

制作 的唯一可行选择放回 工作是要求 Finder 使用 AppleEvents/AppleScript 删除项目。

关于macos - 如何像 Finder 一样丢弃当前用户不拥有的项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56737276/

相关文章:

ios - 如何从连接的 iOS 设备获取电池充电周期?

objective-c - 从代码中确定卷是否为磁盘镜像 (DMG)

php - OSX 中的 xgettext 从 PHP 代码创建 .po 文件

macos - 在终端/脚本中确定 OS X 键盘布局 ("input source")?

objective-c - 不同版本的 Mac OS X 之间的代码分开吗?

.net - 有没有一种方法可以确定文件路径是否嵌套在.Net中的目录路径中

php - Symfony2 什么是最好的文件系统抽象层?

ios - 如何从 iOS 中的文档目录获取文件的创建日期?

ios - NSFileManager:enumeratorAtURL: 返回一个不同形式的 URL 到 NSFileManager:URLForDirectory

objective-c - 创建文件模板?