Jos*_*osh 0 macos cocoa objective-c
我正在尝试使用MacOS X中的"top"命令来确定哪个应用程序正在使用资源.当我做:
top -stats"pid,command"
如果进程名称太长,则截断命令列.
如果查看活动监视器,则会正确显示进程名称(使用全名)+图标.我的问题是:
首先,如果您尝试以编程方式获取数据,那么驾驶top几乎绝对不是您想要做的.
但是,要回答你的直接问题:
如何获得完整的进程名称?
无法控制命令的截断.您可以使用该-ncols参数为非交互式输出设置输出的宽度,但top如果需要,则不会因截断而停止.
有时应用程序图标显示在进程名称旁边,无论如何使用objective-c做类似的事情?我应该只是导航到应用程序内容文件夹并获取icns图像?
不会.您如何处理具有多个.icns文件的应用程序,例如文档图标?(例如,尝试使用iTunes.如果选择第一个.icns,则会获得AIFF文档图标;如果选择最后一个,则会获得内部使用的最近电视节目图标.)
正确的方法是获取NSBundle应用程序,然后执行以下操作:
NSString *iconFile = [bundle objectForInfoDictionaryKey:@"CFBundleIconFile"];
if (iconFile) {
NSString *iconPath = [bundle pathForResource:iconFile ofType:@"icns"];
// load and display the icon
}
Run Code Online (Sandbox Code Playgroud)
那么,如果不是通过驾驶,你如何真正想要这样做top呢?
那么,你所要求的实际上并不是一个定义明确的事情.OS X有四个不同的任务/进程/程序/应用程序概念,它们不一一对应,如果你想编写两个使用不同概念的程序的混搭,那就会让生活变得困难 - 例如,topBSD中的交易进程,而Activity Monitor在OS X应用程序中处理.
如果你真正想要的是同一个列表top使用的,它是开源的,所以你可以阅读它并做同样的事情.
但是为了得到BSD的进程列表的最简单的方法可能是在界面libproc.h特别是proc_listallpids和proc_pidinfo.例如:
int dump_proc_names() {
int buf[16384];
int count = proc_listallpids(&buf, 16384*sizeof(int));
for (int i = 0; i != count; ++i) {
int pid = buf[i];
char path[MAXPATHLEN+1] = {0};
int ret = proc_pidinfo(pid, PROC_PIDPATHINFO, 0,
&path, sizeof(path));
if (ret < 0) {
printf("%d: error %s (%d)\n", pid, strerror(errno), errno);
} else {
printf("%d: %s\n", pid, path);
}
}
}
Run Code Online (Sandbox Code Playgroud)
显然,在实际代码中,您将要动态分配缓冲区,返回值而不是仅仅转储它们,获取的不仅仅是路径等等.但这足以为您提供基本的想法.(当你去获取更多信息时,请注意,如果你要求任何结构,除非你有权查看该结构的每个成员,否则你将收到一个EPERM错误.所以,不要去询问PROC_PIDTASKALLINFO你是否只想要PROC_PIDT_SHORTBSDINFO.
无论如何,由于这个API处理BSD进程(和Mach任务),而不是应用程序,它不会直接帮助你获得NSBundle想要提供Activity Monitor风格的功能.
没有办法做到这一点是完全正确的,但你可能会逃避这样的事情:
NSString *path = processPath;
while (path && ![path isEqualTo:@"/"]) {
NSBundle *bundle = [NSBundle bundleWithPath:path];
if (bundle) {
if ([bundle executablePath != processPath]) return nil;
return bundle;
}
path = [path stringByDeletingLastPathComponent];
}
Run Code Online (Sandbox Code Playgroud)
可能有其他方法可以做到这一点,每个方法都有不同的权衡.例如,使用-[NSWorkspace runningApplications]将结果存储在将bundle可执行路径映射到bundle的字典中,并使用它来查找每个进程很简单,但它似乎只对当前用户拥有的应用程序有用(并且可能在本届会议).另一方面,枚举系统上的所有软件包,或者询问Spotlight或类似软件可能会在运行中做得太慢,但如果你在第一次运行时缓存它们就会过时.
替代的另一种选择libproc是使用libtop.
不幸的是,Apple没有提供它.它们确实有一个libtop实现,它们用于他们的top工具,但它实际上嵌入在源中,top而不是从外部可用.您可以找到源(在上面的链接中)并将其嵌入到您的程序中,就像top它本身一样.
或者,GNU和BSD流程实用程序都有Mac端口(虽然知道在Homebrew/MacPorts/Google搜索中使用哪个名称并不总是很容易......),因此您可以构建其中一个并使用它.
但是,除非您正在尝试编写跨平台软件(或者已经知道如何为Linux或FreeBSD编写此代码),我认为这只会增加额外的复杂性.
| 归档时间: |
|
| 查看次数: |
886 次 |
| 最近记录: |