【问题标题】:Why does TextEdit reject a document's permissions after being launched via FreePascal's TProcess on Max OS X Terminal?为什么 TextEdit 在 Mac OS X 终端上通过 FreePascal TProcess 启动后拒绝文档的权限?
【发布时间】:2016-05-08 16:35:10
【问题描述】:

我正在尝试使用 TProcess 启动 TextEdit,并为其提供一个刚刚由调用程序编写并关闭的文本文件,该调用程序是终端上调用的命令行程序。

我第一次运行它时(见下面的摘录),它可以工作。这种情况是在计算机重新启动后尚未使用 TextEdit 的情况。

在那之后的每一次后续试验中,在之前使用过 TextEdit 之后,TextEdit 都会重新显示一条模态错误消息:

"The document “DocName.PRN” could not be opened. You don’t have permission."

但是使用 GetInfo 我发现权限完全正常,并且使用 TextEdit '手动'打开文件并不困难。

因为 TextEdit 会启动并找到文档,所以我怀疑启动本身有什么问题。我确实尝试过同步启动,但这并没有改变 TextEdit 的权限消息,但确实需要我强制退出 TextEdit,之后调用程序将挂起(无法终止但什么也不做)。

有人知道这里发生了什么,以及如何解决它吗?

...
    procedure launch (prm :array of string; syn :LaunchSyncType);
    var
        X   :integer;
        Proc: TProcess;
    begin
        Proc := TProcess.Create(nil);
        with Proc do begin
            try
                Executable:= prm[0];    {exe;}
                for X := 1 to high(prm) do
                    Parameters.Add(prm[X]);
                InheritHandles := False;
                for X := 1 to GetEnvironmentVariableCount do
                    Environment.Add(GetEnvironmentString(X));
                ShowWindow := swoShow; {used by Windows only}
                if syn = Synchronous then
                    Options := Options + [poWaitOnExit]
                else begin   {asynchronous}
                    Options := [];
                end;
                Execute;
            finally
                Free;
            end;
        end;
    end;
...
    launch( ['/Applications/TextEdit.app/Contents/MacOS/TextEdit',
            '/Users/lor/LorDev/LOR/DocName.PRN'],
            Asynchronous );

【问题讨论】:

  • 我不完全确定我是否遵循了用例,但问题可能是由于沙盒。当沙盒进程创建子进程时,子进程会继承沙盒,但不会继承 PowerBox(打开的对话框)添加的任何临时权限。
  • @Ken 这是一个有趣的建议。我已经使用相同的方法(如上)几次调用其他程序、Adobe 的 PDF 阅读器、打开命令以及我编写的几个程序,但没有一个有任何类似的问题。不过,我会尝试将 InheritHandles 设置为 true,看看会发生什么。
  • @Ken Setting InheritHandles := True 没有任何帮助。我现在通过启动/usr/bin/open 而不是TextEdit 来解决这个问题,但这只是因为我的文档名称后缀是.PRN,它是使用TextEdit 作为默认打开处理程序设置的。它不会帮助任何没有适当的默认打开器的文档名称后缀。
  • 首先,/usr/bin/open 只使用启动服务 API。您可以而且应该直接使用该 API,而不是调用 /usr/bin/open。其次,无论您使用 Launch Services 还是/usr/bin/open,您都可以强制将文档发送到应用程序,即使该应用程序未声明它接受该文档类型。最后,我怀疑InheritHandles 与我对沙盒的建议有什么关系。您的子进程根本不允许访问该文件(通过路径),因为它已被沙盒化,并且没有以一种受支持的方式授予对它的访问权限。
  • @Ken,Xcode 支持的 Swift 或 Objective-C 可以使用 Launch Services API,但是这个程序是用 Free Pascal 编写的,因为它(声称的)跨平台兼容性。 Free Pascal 提供了 TProcess 类,如我的问题所示。为此,可以付出更多努力,在自定义类中实现指向 Apple API 的链接。 Pascal TProcess 类应该提供接口,但它是 TextEdit 的一个功能,它阻止了成功。请注意它在重新启动后第一次是如何工作的,但此后就不行了。因此,沙盒问题是禁忌的。

标签: macos terminal permissions freepascal textedit


【解决方案1】:

@Ken Research 根据您关于启动服务的建议,说服我 FreePascal 提供的 TProcess 类将 TextEdit 作为新实例启动,而不是使用现有实例(如果有的话)。这会产生有问题的单独休眠进程和权限违规。这种方法可能在某种程度上适用于 TProcess 尝试跨平台兼容性的 Windows 环境。当前形式的类不提供控制此行为的选项。因此,让 TProcess 启动 TextEdit 不适合我在 OS X 上的项目。或者,使用带有选项 -e(强制 TextEdit)的 Open 命令是解决我的问题的快速简便的方法。谢谢你给我的方向。

我的启动代码现在如下所示:

launch( ['/usr/bin/open', '-e',
        '/Users/lor/LorDev/LOR/'+DocName+'.PRN'],
        Asynchronous );

【讨论】:

  • Tprocess 也完美地模拟了 *nix。您正在使用的可能更接近 Windows 的 shellexecute,FPC/Lazarus 也没有抽象出来。您可能还想查看 Lazarus 的 OpenDocument 和类似功能
猜你喜欢
  • 2012-06-03
  • 2011-10-15
  • 2020-04-21
  • 2016-04-25
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-12
相关资源
最近更新 更多