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?
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];
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With