检索正在运行的进程的名称

时间:2010-06-10 20:05:58

标签: c objective-c macos process

首先,我知道已经提出了类似的问题,但到目前为止提供的答案并不是很有用(他们都建议使用以下选项之一)。

我有一个用户应用程序需要确定特定进程是否正在运行。以下是我对该过程的了解:

  • 名称
  • 用户(root
  • 已经在运行,因为它是LaunchDaemon,这意味着
  • 其父进程应为launchd(pid 1)

我已经尝试了几种方法来实现这一点,但到目前为止还没有任何方法可行。这是我尝试过的:

  1. 运行ps并解析输出。这很有效,但速度很慢(fork / exec很贵),我希望这一点尽可能快。

  2. 使用GetBSDProcessList函数listed here。这也有效,但他们说检索进程名称(从每个kp_proc.p_comm结构访问kinfo_proc)的方式是有缺陷的。结果char*仅包含进程名称的前16个字符,可以在kp_proc结构的定义中看到:

    #define MAXCOMLEN 16 //defined in param.h
    struct extern_proc {  //defined in proc.h
      ...snip...
      char p_comm[MAXCOMLEN+1];
      ...snip...
    };
  3. 使用libProc.h检索流程信息:

    pid_t pids[1024];
    int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);   
    proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));    
    for (int i = 0; i < numberOfProcesses; ++i) {
      if (pids[i] == 0) { continue; }
      char name[1024];
      proc_name(pids[i], name, sizeof(name));
      printf("Found process: %s\n", name);
    }

    这有效,除了它与GetBSDProcessList具有相同的缺陷。仅返回流程名称的第一部分。

  4. 在Carbon中使用ProcessManager function

    ProcessSerialNumber psn;
    psn.lowLongOfPSN = kNoProcess;
    psn.highLongOfPSN = 0;
    while (GetNextProcess(&psn) == noErr) {
      CFStringRef procName = NULL;
      if (CopyProcessName(&psn, &procName) == noErr) {
        NSLog(@"Found process: %@", (NSString *)procName);
      }
      CFRelease(procName);
    }

    这不起作用。它只返回向WindowServer注册的进程(或类似的东西)。换句话说,它只返回带有UI的应用程序,并且只返回当前用户。

  5. 我无法使用-[NSWorkspace launchedApplications],因为它必须与10.5兼容。此外,这仅返回有关当前用户在Dock中显示的应用程序的信息。

  6. 我知道可能来检索正在运行的进程的名称(因为ps可以这样做),但问题是“我能不执行而不执行{exec'ing { {1}}?”。

    有什么建议吗?

    修改

    经过更多的研究后,我一直无法找到办法。我找到了this SO question,其中提到了this C file in a python module。这对于尝试在ps调用中使用KERN_PROCARGS值非常有用。

    但是,Python模块代码似乎源自sysctlwhich I found hereps可以某种方式获取每个正在运行的进程的可执行路径,但我尽最大努力提取如何执行此操作是不成功的。 ps中有一个名为print.c的函数似乎正在发挥作用,但是当我从我自己的命令行工具中运行相同的代码时,我无法检索任何进程的进程可执行文件不是我自己的。

    我会继续尝试,但如果没有更确凿的证据,看起来@drawonward的答案到目前为止是最正确的。


    编辑(很久以后)

    感谢答案pointed to by Quinn Taylor,我找到了有效的方法。它获取每个进程的可执行路径,然后我可以抓住最后一个路径组件来获取实际的进程名称。

    getproclline

3 个答案:

答案 0 :(得分:8)

相关问题的答案怎么样? https://stackoverflow.com/a/12274588/120292这声称可以通过pid获取进程的完整路径,并且您可以只获取最后一个路径组件。

答案 1 :(得分:2)

上面2中提供了运行进程的唯一完整列表,询问内核。获取流程的实际名称并不是直截了当的。简而言之,您可以在找到匹配项之前查找任何其他来源的pid。

对于某些流程,以下内容将起作用:

ProcessSerialNumber         psn;
CFStringRef             name = NULL;
status = GetProcessForPID( inPID , &psn );
if ( noErr == status ) CopyProcessName( &psn , &name );

对于某些流程,您可以在[[NSWorkspace sharedWorkspace] launchedApplications] NSApplicationProcessIdentifier的结果中查找pid。适用于10.2及更高版本。此列表中的大多数(但可能不是全部)项目与上面的CopyProcessName相同。

对于某些进程,您可以查找进程参数并从第一个参数获取完整路径。与获取原始列表类似,但使用KERN_PROCARGS或KERN_PROCARGS2作为第二个mib值。这就是ps正在做的事情。

对于某些进程,您会遇到16个字符的p_comm。

答案 2 :(得分:0)

不确定这是否是您要找的,但是您可以将LaunchServices API与__ LSCopyApplicationArrayInFrontToBackOrder一起使用吗?我听说过这个,但从来没有用过它。经过一些谷歌搜索,这里有一个代码示例可能提供您正在寻找的东西?我真的不知道,我猜一点;)

http://gist.github.com/163918

<强> 修改

实际上,哈。这是一个Stack Overflow帖子,它将此作为答案并链接到我链接到的相同帖子...

http://www.stackoverflow.com/questions/945033/getting-the-list-of-running-applications-ordered-by-last-use