Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to get the PID of a recently launched application

I want to launch a file with a specified application, and I want the launched program to immediately become the frontmost window.

I know that I can do this as follows:

[[NSWorkspace sharedWorkspace] openFile:fileName withApplication:appName];

Then, if I can get the PID of that launched application, I can then do this to make that application frontmost:

NSRunningApplication* app = [NSRunningApplication
                             runningApplicationWithProcessIdentifier: PID];
[app activateWithOptions: NSApplicationActivateAllWindows];

The question I have is this: what is the simplest, quickest, and most reliable way to get this application's PID right after launching, so I can make sure that this application is frontmost?

This is not as straightforward as it might appear at first glance. For example, I need a process name in order to get the PID using Carbon calls, or via the application dictionary that is accessible via NSRunningApplication. However, in the general case, I don't always know what the process name is, and in some cases, the process name is an empty string.

Furthermore, I might have other instances of this same application already running, and I want to always get the PID of the specific instance of the application that I just launched.

Can anyone suggest a definitive, 100-percent reliable way to get the currently launched application's PID?

Or alternatively, is there a way to launch a given file with a specified application such that the application always opens as the frontmost app?

like image 998
HippoMan Avatar asked Nov 04 '22 04:11

HippoMan


2 Answers

Have you tried using the other version of openFile which will allow you to deactivate your application, allowing the new application to take focus?

[[NSWorkspace sharedWorkspace] openFile:fileName withApplication:appName andDeactivate:YES];
like image 142
kennbrodhagen Avatar answered Nov 15 '22 05:11

kennbrodhagen


It is definitely not easy to get the PID of an application. And that's how Apple likes it.. Those cheeky bastards.

I had to write this beast just to get the PID from a full path of an app I knew was running.. Hey it's easier than parsing ps aux !

Sorry if there are some of my own private functions in there but you can get the idea of how I went about it and what I tried to avoid along the way.

+ (NSUInteger)pidFromAppPath:(NSString*)path
{
   NSRunningApplication *n = [[[NSWorkspace sharedWorkspace]runningApplications] filterOne:^BOOL(NSRunningApplication *runner) {
      // optional:  avoid totally faceless apps and "Desk Accesory"-type background apps.
      if (runner.activationPolicy == NSApplicationActivationPolicyProhibited) ||
          runner.activationPolicy == NSApplicationActivationPolicyAccessory) 
          return nil;
      id runPath = [runner valueForKeyPath:@"bundleURL"];
      NSString *runString = [runPath isKindOfClass:[NSString class]]
                          ? runPath
                          : [runPath isKindOfClass:NSURL.class] ? [((NSURL*)runPath) path] 
                          : nil;
     // optional: filter out Google Chrome's mockery of a once sane process-table
     if ( !runString
          || [[runString lastPathComponent]contains:@"Google Chrome Helper.app"]    
          || [[runString lastPathComponent]contains:@"Google Chrome Worker.app"]    
          || [[runString lastPathComponent]contains:@"Google Chrome Renderer.app"] ) 
     return nil;
     return  [runString isEqualToString:path] ?: nil;  // This is where you actually test to see if it's the same as the string passed in, lol.
    }];
    return  n ? [n processIdentifier] : 11000;  //  if 11000 you messed up.
}

And voilá... NSLOG: Pid of /Applications/Utilities/Terminal.app is 46152

like image 29
Alex Gray Avatar answered Nov 15 '22 06:11

Alex Gray