Самый простой способ получить PID недавно запущенного приложения - PullRequest
5 голосов
/ 11 марта 2012

Я хочу запустить файл с указанным приложением и хочу, чтобы запущенная программа сразу стала самым передним окном.

Я знаю, что могу сделать это следующим образом:

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

Затем, если мне удастся получить PID этого запущенного приложения, я смогу сделать это, чтобы приложение было первым:

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

Вопрос, который у меня возникает, заключается в следующем: каков самый простой, быстрый и надежный способ получить PID этого приложения сразу после запуска, чтобы я мог убедиться, что это приложение является передним?

Это не так просто, как может показаться на первый взгляд. Например, мне нужно имя процесса, чтобы получить PID с помощью вызовов Carbon или через словарь приложения, доступный через NSRunningApplication. Однако в общем случае я не всегда знаю, как называется процесс, а в некоторых случаях имя процесса представляет собой пустую строку.

Кроме того, у меня уже могут быть запущены другие экземпляры этого приложения, и я хочу всегда получать PID конкретного экземпляра приложения, которое я только что запустил.

Кто-нибудь может предложить точный, 100-процентный надежный способ получения PID запущенного приложения?

Или, альтернативно, есть ли способ запустить указанный файл с указанным приложением, чтобы приложение всегда открывалось как самое переднее приложение?

Ответы [ 2 ]

1 голос
/ 01 марта 2013

Определенно не легко получить 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.
}

И вуаля ... NSLOG: Pid of /Applications/Utilities/Terminal.app is 46152

1 голос
/ 11 марта 2012

Вы пытались использовать другую версию openFile, которая позволит вам деактивировать ваше приложение, позволяя новому приложению сфокусироваться?

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