5

我想为 OSX 捕获所有正在运行的进程的列表,并将它们保存为 Xcode/Cocoa 中的文件。我用谷歌搜索了这个,我发现的是:

[myWorkspace runningApplications];

我不知道该怎么做。请帮忙!谢谢!

4

2 回答 2

13

正如QA1123中所解释的,“进程”意味着 Mac 上的多个不同事物(并且随着时间的推移而变化)。

Cocoa(或 Carbon,或从前经典)级别的“流程”基本上是最终用户认为的流程:应用程序、fba、launchitem 等。 BSD 是受过 Unix 培训的系统管理员所认为的进程:出现在ps. 一个高级进程可以有多个 BSD 进程;反过来也可以(在经典下);您还可以拥有没有高级进程的 BSD 进程;等等

如果您想要高级定义,请忘记 QA,-[NSWorkspace runningApplications]您提到的方法会返回您想要的内容:一个包含每个此类应用程序的对象的数组,并且这些对象包含您想要的所有信息。如何将它们保存在文件中取决于您想要关于每个应用的哪些信息、您希望以什么格式保存该信息等。这是一个完整的示例应用程序,它将每个应用程序的 URL(每行一个)保存到文件中称为“./appslist”:

#include <Cocoa/Cocoa.h>

int main(int argc, char *argv[]) {
  NSString *output = [NSString string];
  for (NSRunningApplication *app in 
       [[NSWorkspace sharedWorkspace] runningApplications]) {
    output = [output stringByAppendingFormat:@"%@\n",
                     [[app bundleURL] absoluteString]];
  }
  [output writeToFile:@"./appslist" 
           atomically:YES
             encoding:NSUTF8StringEncoding
                error:NULL];
  return 0;
}

如果您想要低级定义,那么 QA 中的代码仍然是准确的。或者你可以只是exec(or systemor NSTask) ps

无论如何,这里有一个示例(使用来自 QA 的代码)将每个正在运行的进程的 pid 打印到名为“./bsdlist”的本地文件中:

int main(int argc, char *argv[]) {
  kinfo_proc *procs;
  size_t count;
  int err = GetBSDProcessList(&procs, &count);
  if (err) return err;
  FILE *f = fopen("./bsdlist", "w");
  for (size_t i=0; i!=count; ++i) {
    fprintf(f, "%d\n", procs[i].kp_proc.p_pid);
  }
  fclose(f);
  free(procs);
}

如果您喜欢脚本的想法,ps如上所述,有很多方法可以做到这一点。

Dominik 的回答中提到的DDTask库看起来是最简单的方法。如果你想NSTask直接使用,它需要更多的代码来设置一个NSPipe标准输出等。有一个很好的通用CocoaDev(它是脚本ls而不是脚本ps,但想法都是一样的。)

或者你可以降到一个较低的水平。您可以显式地fork/exec并通过 stdout 传递结果,但是该popen函数旨在将所有这些都包装起来,并且使用起来要容易得多。GNU C Programming Tutorial展示了如何将popen ps -A其通过管道传输到grep init; 这就是你所需要的前半部分。

无论你走哪条路,问题是你会得到一堆你必须解析的字符串。最好的办法是传递不同的标志来ps只得到你真正想要的。如果你想要的只是命令行,ps -ax -ocommand=那么只会给你一个命令行,每行一个命令行——没有要跳过的标题行,没有要解析的列,等等。

如果您担心效率:QA 说“执行 ps 将需要解析工具的输出,并且不会像清单 1 那样有效地使用系统资源。” 这是真的;将输出格式化sysctl为字符串只是为了将它们通过管道传递并再次解析它们是额外的工作,必须花费一些CPU 时间。但除非你这样做数百万次,否则我怀疑它是否足以产生影响。最好的方法(对此,以及大多数情况)是先编写更简单的代码并测试它是否足够快;如果是,你就完成了。

于 2012-09-14T23:00:47.233 回答
1

yip 获取高级查询工作区,如 abarnet 所示,以获取“所有”进程进入较低级别并通过 NSTask 执行 ps 并通过 NSPipe 读取响应。

有苹果的示例代码..或使用 DDTask(我写的一个包装器)github存储库

NSString *exe = @"/bin/ps";
NSArray *args = @[@"-ax"];
NSString *res = [DDTask runTaskWithToolPath:exe andArguments:args andErrorHandler:nil];

[res writeToFile:@"./appslist" 
      atomically:YES
        encoding:NSUTF8StringEncoding
           error:NULL];
于 2012-09-14T23:13:21.267 回答