4

For example, a user puts my application on his/her desktop. Then he/she copied (instead of moving) it to the /Application folder.

If the one at ~/Desktop has been launched, how can I prevent duplicated launching of the one at ~/Application? Any simple way?

Or if the user launches the one in /Application, I can detect the pre-launched app, and then switch to that immediately?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Andrew Chang
  • 1,289
  • 1
  • 18
  • 38
  • 3
    Register a mach port. I wrote a gist about this a while ago https://gist.github.com/CodaFi/5639819 – CodaFi Mar 31 '14 at 07:24
  • I'm stunned that OS X actually *launches* a second instance of the app in that scenario in the first place.. – cacau Mar 31 '14 at 08:54

3 Answers3

3

How about getting a list of all running applications and quitting immediately if your app detects there's another instance already running?

You can get a list of all active apps via NSWorkspace and runningApplications:

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSArray *allRunningApps = [ws runningApplications];

It'll return an array of NSRunningApplication instances so all you'd have to do is check the list for e.g. your app's ID via the bundleIdentifier method.

cacau
  • 3,606
  • 3
  • 21
  • 42
  • Haha! Actually you have solve the "check duplication" part. But I was still studying on "bring the previous one to front" part. I found a solution [HERE](http://stackoverflow.com/questions/2333078/how-to-launch-application-and-bring-it-to-front-using-cocoa-api), but the "-activateWithOptions" did not work for me. – Andrew Chang Mar 31 '14 at 09:26
  • I have found another solution which fits my question more. But still, thank you very much!!! – Andrew Chang Mar 31 '14 at 11:46
1

cacau's answer had given me inspiration to achieve my goal. Here are my codes (ARC):

- (BOOL)checkAppDuplicateAndBringToFrontWithBundle:(NSBundle *)bundle
{
    NSRunningApplication *app;
    NSArray *appArray;
    NSUInteger tmp;
    pid_t selfPid;
    BOOL ret = NO;

    selfPid = [[NSRunningApplication currentApplication] processIdentifier];
    appArray = [NSRunningApplication runningApplicationsWithBundleIdentifier:[bundle bundleIdentifier]];

    for (tmp = 0; tmp < [appArray count]; tmp++)
    {
        app = [appArray objectAtIndex:tmp];

        if ([app processIdentifier] == selfPid)
        {
            /* do nothing */
        }
        else
        {
            [[NSWorkspace sharedWorkspace] launchApplication:[[app bundleURL] path]];
            ret = YES;
        }
    }

    return ret;
}

It checks app duplicate by bundle identifier. As bundle duplicated, it brings all other applications to front and returns YES. As receiving YES, application can terminate itself.

However, as cacau has given me significant help, I gave him the reputation point of this question. Thank you!

Andrew Chang
  • 1,289
  • 1
  • 18
  • 38
  • Thanks! Couldn't figure out how to filter out the currently running app and idk why I didn't think of checking the pid. – thecoolwinter Aug 01 '22 at 15:02
0

Would it not be simplest to actually just create a file inside NSTempDirectory, check for it and if it is there, you quit, or perhaps offer a way to delete the file ? This would work for both running in and out of sandbox.

Trausti Thor
  • 3,722
  • 31
  • 41
  • Sounds kinda hacky, though - we do have better possiblities in Cocoa to perform more sophisticated checks.. – cacau Mar 31 '14 at 12:16