在Mac上使用单实例应用程序的理想方式

时间:2009-07-04 00:42:13

标签: cocoa macos mutex

在Windows上,通常的做法是创建一个已命名的互斥锁,并使用它来确定给定应用程序的实例是否已在运行。这有其缺点,但大多数都有效。

我可以想办法在Mac上执行此操作:

  1. 命名为pthread mutexes
  2. 枚举正在运行的进程并查找匹配
  3. 的进程
  4. 创建并锁定文件
  5. Cocoa / Carbon内置的东西比上面的选项更容易吗?如果没有,那三个中哪一个最常用于mac?我会假设2或3 ...

6 个答案:

答案 0 :(得分:8)

进一步详细说明使用NSWorkspace。尝试在NSWorkspace中使用launchApplications。这将返回一个NSArray,其中包含每个已启动应用程序的字典。您可以遍历数组以查看您要查找的应用程序是否已在运行。我建议您使用值为NSApplicationBundleIdentifier的值,该值将具有“com.mycompany.myapp”之类的值,而不是查找名称。如果您需要查找应用程序的软件包标识符,可以查看应用程序包中的info.plist文件。

答案 1 :(得分:6)

Mac没有与Windows一样的实例。一般来说,您希望应用程序运行两次,您需要复制二进制文件,然后双击复制的版本。

如果您需要运行两个应用程序实例,那么您不会像Mac用户那样思考:)。

编辑:技术上不正确。检查评论。

答案 2 :(得分:1)

不同操作系统之间的映射流程管理不起作用。或者效果不好。默认情况下,如果没有特别的努力,您只能获得一份副本和一份应用程序副本。

这是一个先前类似的问题,比当前的问题更进一步,并且有一些回复讨论了当有多个图像副本或需要协调的多个应用程序时的互锁。

How to detect whether an OS X application is already launched

有关运行时上下文的介绍,特别是围绕Mac OS X守护进程和代理(以及当您需要运行可执行文件的多个副本,作为池或类似于Apache的情况)时,见:

http://developer.apple.com/technotes/tn2005/tn2083.html

答案 3 :(得分:1)

如果您正在编写Cocoa应用程序,则可以使用NSWorkspace查看另一个进程是否正在使用您的包标识符运行。我看过几个提出对话框的应用程序并说:“这个应用程序的一个实例已经在运行” - 我认为Firefox实际上是这样做的。

这不是一个非常“mac-ish”的方法,但它会完成工作。

答案 4 :(得分:0)

如果您使用Java Web Start(JWS)部署应用程序,则可以使用javax.jnlp.SingleInstanceService。 JWS配置还将提供自动程序更新。

答案 5 :(得分:0)

以下代码可用于已运行的具有相同捆绑标识符的退出应用程序。

执行此操作后它还会显示警报。

AppDelegate.applicationDidFinishLaunching

let runningApp =
    NSWorkspace.shared.runningApplications
        .filter { item in item.bundleIdentifier == Bundle.main.bundleIdentifier }
        .first { item in item.processIdentifier != getpid() }

if let running = runningApp {
    running.forceTerminate()
    
    let alert = NSAlert()
    alert.messageText = "App was alreday running"
    alert.informativeText = "App was terminated."
    alert.alertStyle = NSAlert.Style.informational
    alert.addButton(withTitle: "OK")
    alert.runModal()
}

注意:这假设只有一个已在运行的应用程序。适应其他场景应该是微不足道的。

相关问题