在 Windows 上,通常的做法是创建一个命名互斥体并使用它的存在来确定给定应用程序的实例已经在运行。这有其缺点,但大多数情况下都有效。
我可以想办法在 Mac 上做到这一点:
- 命名 pthread 互斥体
- 枚举正在运行的进程并查找匹配的进程
- 创建和锁定文件
可可/碳中是否有比上述选项更容易的东西?如果不是,这三个中哪一个在 mac 上最常用?我会假设2或3 ...
进一步详细说明使用 NSWorkspace。尝试在 NSWorkspace 中使用 launchApplications。这将返回一个 NSArray,其中包含每个启动的应用程序的字典。您可以遍历数组以查看您要查找的应用程序是否已在运行。我建议您使用带有键 NSApplicationBundleIdentifier 的值,该值将具有类似“com.mycompany.myapp”的值,而不是查找名称。如果您需要查找应用程序的捆绑标识符,您可以查看应用程序包中的 info.plist 文件。
Mac 没有 Windows 那样的实例。一般来说,您希望应用程序运行两次,您需要复制二进制文件,然后双击复制的版本。
如果您需要运行应用程序的两个实例,那么您不会像 Mac 用户那样思考 :)。
编辑:这在技术上是不正确的。检查评论。
在不同的操作系统之间映射进程管理不起作用。或者效果不好。默认情况下,无需特别努力,您将获得一份应用程序的副本,并且只有一份副本。
这是以前的类似问题,比当前的问题更进一步,并且有一些答复讨论了在图像有多个副本或需要协调的多个应用程序时互锁的问题。
有关运行时上下文的介绍,尤其是围绕 Mac OS X 守护进程和代理的介绍(对于那些确实需要运行多个可执行文件副本的情况,例如池等,类似于 Apache),请参阅:
如果您正在编写 Cocoa 应用程序,您可以使用 NSWorkspace 查看是否有另一个进程正在使用您的包标识符运行。我见过一些应用程序会显示一个对话框并说:“这个应用程序的一个实例已经在运行”——我认为 Firefox 确实做到了。
这不是一种非常“mac-ish”的方法,但它可以完成工作。
如果要使用 Java Web Start (JWS) 部署应用程序,则可以使用javax.jnlp.SingleInstanceService。JWS 供应还将提供自动程序更新。
以下代码可用于已运行的具有相同捆绑标识符的退出应用程序。
这样做后它还会显示警报。
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()
}
注意:这假设只能有一个已经在运行的应用程序。应该很容易适应其他场景。