【问题标题】:Services menu launches wrong application bundle服务菜单启动错误的应用程序包
【发布时间】:2015-10-18 23:14:01
【问题描述】:

我已经基于 Apple 文档中的“simpleEncrypt”示例实现了一个 MacOS 服务。我正在运行 10.9 和 Xcode 6.2。

我可以构建应用程序包,将其复制到 /Applications,运行一次,我的服务将按预期出现在其他应用程序的服务菜单中。

如果我运行“pbs -dump_pboard”,我的应用程序包的正确路径将显示为 NSBundlePath,正如预期的那样。

但是,当我从“服务”菜单中选择我的服务时,MacOS 将启动我的应用程序的旧副本,该副本位于 ~/Library/Developer/Xcode/Archives。

如果我删除那个旧副本,它将从其他地方运行另一个副本。只有在我删除文件系统上与我的服务的 NSPortName 具有相同 CFBundleName 的所有其他应用程序包之后,MacOS 才会从 /Applications 启动正确的应用程序包。当它发生时,服务会正常工作。

如何让 MacOS 可靠地为我的服务调用正确的应用程序包?

【问题讨论】:

    标签: objective-c xcode macos cocoa service


    【解决方案1】:

    在 OS X 中,应用程序注册到 Launch Services,它负责在请求时执行应用程序,方法是双击其应用程序包,通过 Spotlight,或者在您的情况下,从“服务”菜单运行。

    注册是自动进行的,例如,当应用程序被复制到 /Applications 文件夹(它不仅仅复制文件)或什至只是运行进程时。

    可以通过运行带有-dump 参数的lsregister 命令来查看已注册应用程序的列表。在 OS X 10.10 上,它会是这样的:-

    /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump
    

    由于您有同一个应用程序的多个副本,它们的注册详细信息是相同的,因此 Launch Services 不会更新其数据库,而只会执行与注册详细信息匹配的第一个看到的应用程序。

    Apple docs 中,它建议您可以使用LSRegisterFSRefLSRegisterURL 函数在代码中注册应用程序,使用inUpdate 布尔参数,或者:

    更新应用程序的修改时间,以确保它会被自动注册实用程序更新

    我希望您仍然必须直接运行该应用程序,以确保 Launch Services 更新其数据库。对于捆绑包,您可以直接导航到应用程序的二进制文件。以 Caculator.app 为例,您将执行:-

    /Applications/Calculator.app/Contents/MacOS/Calculator
    

    我发现的另一个选项是通过增加版本号来更新应用程序的 Info.plist,或者更彻底地,更改其 CFBundleIdentifier。

    【讨论】:

    • 感谢您的回复。
    • 在我的情况下,将 .app 包复制到 /Applications 和/或运行它会导致系统重新读取其 .plist(如预期的那样),这已由更新的 NSMenuItem 字符串确认服务菜单。 However, when the menu item was selected, it attempted to run a copy of the service itself from another location.正如我所提到的,“pbs -dump_pboard”显示了该服务的正确 NSBundlePath。但是,如果我运行 'lsregister -kill',然后运行 ​​'lsregister -seed -dump',则数据库似乎可以合理地重建,并且可以正常工作。
    • 是的,它从不同的位置运行服务;首次注册的那个。使用lsregister -kill 重置启动服务数据库,lsregister -seed 重新扫描并注册找到的应用程序。然而,拥有同一个应用程序的多个版本仍然会让人感到困惑,但至少你现在知道为什么了。
    • 完成。仍然感觉像一个错误,即 Launch Services 在遇到新包时应该只更新其数据库,并且当找不到服务包时,它应该优先考虑它在非标准位置发现的那些,而不是它已经知道的那个关于在 /Applications 中。
    • 如果捆绑包是“新的”,它的 Info.plist 中应该有更高的版本号。它只是在比较时不考虑修改或创建时间。
    猜你喜欢
    • 2013-05-12
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 2015-07-22
    • 2013-07-05
    相关资源
    最近更新 更多