How to detect whether an OS X application is already launched

前端 未结 9 1589
自闭症患者
自闭症患者 2020-12-14 02:46

Normally an application bundle on OS X can only be started once, however by simply copying the bundle the same application can be launched twice. What\'s the best strategy t

相关标签:
9条回答
  • 2020-12-14 03:03

    What about IPC? You could open a socket and negotiate with the other launched instance. You'd have to be careful though, that it works if both apps start at the same time.

    I can't provide you with sample code, as I haven't (yet, but I will soon) used it.

    0 讨论(0)
  • 2020-12-14 03:08

    This is a combination of Romans' and Jeff's answers for Swift 2.0: If another instance of the app with the same bundle ID is already running, show an alert, activate the other instance and quit the duplicate instance.

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        /* Check if another instance of this app is running. */
        let bundleID = NSBundle.mainBundle().bundleIdentifier!
        if NSRunningApplication.runningApplicationsWithBundleIdentifier(bundleID).count > 1 {
            /* Show alert. */
            let alert = NSAlert()
            alert.addButtonWithTitle("OK")
            let appName = NSBundle.mainBundle().objectForInfoDictionaryKey(kCFBundleNameKey as String) as! String
            alert.messageText = "Another copy of \(appName) is already running."
            alert.informativeText = "This copy will now quit."
            alert.alertStyle = NSAlertStyle.CriticalAlertStyle
            alert.runModal()
    
            /* Activate the other instance and terminate this instance. */
            let apps = NSRunningApplication.runningApplicationsWithBundleIdentifier(bundleID)
            for app in apps {
                if app != NSRunningApplication.currentApplication() {
                    app.activateWithOptions([.ActivateAllWindows, .ActivateIgnoringOtherApps])
                    break
                }
            }
            NSApp.terminate(nil)
        }
    
        /* ... */
    }
    
    0 讨论(0)
  • 2020-12-14 03:10

    First off, it's “Mac OS X” or “OS X”. There is no such thing as “OS/X”.

    Second, Mac OS X doesn't come with Boost; you would need to bundle it with your application.

    Third, most of Carbon is not available in 64-bit. This is a clear signal that those portions of Carbon will go away someday (when Apple abandons 32-bit in its hardware). Sooner or later, you will have to either rewrite your app with Cocoa or abandon the Mac.

    Normally an application bundle on OS/X can only be started once, however by simply renaming the bundle the same application can be launched twice.

    No it can't. Launching the renamed or moved application will simply activate (bring to the front) the process that was already running; it won't start a new, second process alongside the first one.


    There are several ways to tell whether an application is already running. In each case, you do this on launch:

    1. Use Cocoa's NSConnection to register a connection with a single constant name. This will fail if the name is already registered. (You can use Foundation from a Carbon app; it's the Application Kit you have to be careful with.)
    2. Use the Process Manager to scan the process list for processes whose bundle identifier match the one you're looking for. The bundle identifier isn't unchangeable, but it's harder to change than the filename or location.
    3. If you're looking to see when someone runs a second copy of yourself, you can use CFNotificationCenter:

      1. Add yourself as an observer for “com.yourdomain.yourappname.LaunchResponse”.
      2. Post a notification under the name “com.yourdomain.yourappname.LaunchCall”.
      3. Add yourself as an observer for “com.yourdomain.yourappname.LaunchCall”.

      In your observation callback for the Call notification, post the Response notification.
      In your observation callback for the Response notification, exit.

      Thus, when the first process starts, it will Call and get no Response; when the second process starts, it will Call, get a Response from the first process, and exit in deference to the first.

    0 讨论(0)
提交回复
热议问题