获取最近启动的应用程序的PID的最简单方法

时间:2012-03-11 15:13:11

标签: objective-c macos cocoa launch pid

我想用指定的应用程序启动一个文件,我希望启动的程序立即成为最前面的窗口。

我知道我可以这样做:

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

然后,如果我可以获得启动的应用程序的PID,那么我可以这样做以使该应用程序最前面:

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

我的问题是:启动后立即获取此应用程序的PID的最简单,最快捷,最可靠的方法是什么,所以我可以确保这个应用程序是最前面的?

这并不像第一眼看上去那么简单。例如,我需要一个进程名称,以便使用Carbon调用获取PID,或者通过NSRunningApplication可访问的应用程序字典。但是,在一般情况下,我并不总是知道进程名称是什么,在某些情况下,进程名称是空字符串。

此外,我可能已经运行了同一个应用程序的其他实例,并且我希望始终获得刚刚启动的应用程序的特定实例的PID。

有人能建议一种确定的,100%可靠的方式来获取当前启动的应用程序的PID吗?

或者,有没有办法用指定的应用程序启动给定文件,以便应用程序始终作为最前面的应用程序打开?

2 个答案:

答案 0 :(得分:1)

您是否尝试过使用其他版本的openFile来停用您的应用程序,让新应用程序成为焦点?

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

答案 1 :(得分:1)

获取应用程序的PID绝对不容易。这就是Apple喜欢它的方式..那些厚颜无耻的混蛋。

我必须写这个野兽只是为了从我知道正在运行的应用程序的完整路径中获取PID。嘿它比解析ps aux更容易!

很抱歉,如果我有一些自己的私人功能,但你可以了解我是如何去做的,以及我在此过程中试图避免的。

+ (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.
}

vo ... NSLOG: Pid of /Applications/Utilities/Terminal.app is 46152