macos 以编程方式检查进程是否在 Mac 上运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2518160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Programmatically check if a process is running on Mac
提问by psychotik
Is there any Carbon/Cocoa/C API available on Macs that I can use to enumerate processes? I'm looking for something like EnumProcesses
on Windows.
Mac 上是否有任何可用的 Carbon/Cocoa/C API 可用于枚举进程?我正在寻找类似EnumProcesses
Windows 的东西。
My goal is to check from code whether a process is running (by name).
我的目标是从代码中检查进程是否正在运行(按名称)。
Thanks!
谢谢!
采纳答案by psychotik
TechZen says:The Process Manager is, as of Dec 2013, completely deprecated.
TechZen 表示:流程管理器自 2013 年 12 月起已完全弃用。
Ah, I just found the Process Manager reference
啊,我刚刚找到了流程管理器参考
Looks like GetNextProcess
and GetProcessInfo
help in figuring out what's running. As suggested by Dave, GetBSDProcessList
can be used if you're looking for daemons and not just Carbon/Cocoa processes.
看起来GetNextProcess
并GetProcessInfo
有助于找出正在运行的内容。正如 Dave 所建议的,GetBSDProcessList
如果您正在寻找守护进程而不仅仅是 Carbon/Cocoa 进程,则可以使用它。
回答by valexa
Here are some specific implementations and details, note that proc->kp_proc.p_comm has a character length limit that's why I'm implemented infoForPID: instead
这里有一些具体的实现和细节,注意 proc->kp_proc.p_comm 有一个字符长度限制,这就是我实现 infoForPID 的原因:
Cocoa :
可可 :
[NSWorkspace launchedApplications] (10.2+ , deprecated in 10.7, very limited process listing) [NSWorkspace runningApplications] (10.6+ , less limited process listing but still not including daemon processes)
[NSWorkspacelaunchApplications](10.2+,在 10.7 中弃用,非常有限的进程列表) [NSWorkspace runningApplications](10.6+,较少限制的进程列表但仍然不包括守护进程)
Carbon :
碳 :
- (NSArray*)getCarbonProcessList
{
NSMutableArray *ret = [NSMutableArray arrayWithCapacity:1];
ProcessSerialNumber psn = { kNoProcess, kNoProcess };
while (GetNextProcess(&psn) == noErr) {
CFDictionaryRef cfDict = ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask);
if (cfDict) {
NSDictionary *dict = (NSDictionary *)cfDict;
[ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"%@",[dict objectForKey:(id)kCFBundleNameKey]],@"pname",
[NSString stringWithFormat:@"%@",[dict objectForKey:@"pid"]],@"pid",
[NSString stringWithFormat:@"%d",(uid_t)getuid()],@"uid",
nil]];
CFRelease(cfDict);
}
}
return ret;
}
C: (see Technical Q&A QA1123 Getting List of All Processes on Mac OS X)
C:(参见技术问答 QA1123 获取 Mac OS X 上的所有进程列表)
- (NSArray*)getBSDProcessList
{
NSMutableArray *ret = [NSMutableArray arrayWithCapacity:1];
kinfo_proc *mylist;
size_t mycount = 0;
mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc));
GetBSDProcessList(&mylist, &mycount);
int k;
for(k = 0; k < mycount; k++) {
kinfo_proc *proc = NULL;
proc = &mylist[k];
NSString *fullName = [[self infoForPID:proc->kp_proc.p_pid] objectForKey:(id)kCFBundleNameKey];
if (fullName == nil) fullName = [NSString stringWithFormat:@"%s",proc->kp_proc.p_comm];
[ret addObject:[NSDictionary dictionaryWithObjectsAndKeys:
fullName,@"pname",
[NSString stringWithFormat:@"%d",proc->kp_proc.p_pid],@"pid",
[NSString stringWithFormat:@"%d",proc->kp_eproc.e_ucred.cr_uid],@"uid",
nil]];
}
free(mylist);
return ret;
}
- (NSDictionary *)infoForPID:(pid_t)pid
{
NSDictionary *ret = nil;
ProcessSerialNumber psn = { kNoProcess, kNoProcess };
if (GetProcessForPID(pid, &psn) == noErr) {
CFDictionaryRef cfDict = ProcessInformationCopyDictionary(&psn,kProcessDictionaryIncludeAllInformationMask);
ret = [NSDictionary dictionaryWithDictionary:(NSDictionary *)cfDict];
CFRelease(cfDict);
}
return ret;
}
回答by Dave DeLong
There are a couple ways you can do this:
有几种方法可以做到这一点:
- If it's a GUI app with a Dock icon, use
-[NSWorkspace launchedApplications]
. - Fork off another process (like ps or top or whatever) via an
NSTask
, read the results, and search yourself (or pipe it through grep or something). - Use the
GetBSDProcessList
function described here: http://developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html(I've used this successfully in the past)
- 如果它是带有 Dock 图标的 GUI 应用程序,请使用
-[NSWorkspace launchedApplications]
. - 通过 an 分叉另一个进程(如 ps 或 top 或其他)
NSTask
,读取结果,并搜索自己(或通过 grep 或其他方式进行管道搜索)。 - 使用
GetBSDProcessList
这里描述的功能:http: //developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html(我过去曾成功使用过)
回答by ericg
In the overview of the NSRunningApplicationClass, it says:
在NSRunningApplicationClass的概述中,它说:
NSRunningApplication is a class to manipulate and provide information for a single instance of an application. Only user applications are tracked; this does not provide information about every process on the system.
NSRunningApplication 是一个为应用程序的单个实例操作和提供信息的类。仅跟踪用户应用程序;这并不提供有关系统上每个进程的信息。
and
和
To access the list of all running applications, use the runningApplications method in NSWorkspace.
要访问所有正在运行的应用程序的列表,请使用runningApplications方法NSWorkspace。
I would suggest taking a look at Workspace Services Programming Topics
我建议看看工作区服务编程主题
回答by samvv
Late to the party, but if you really need a robust solution that can check whether anyprocess is running (including BSD processes), you can do the following:
晚了,但如果你真的需要一个强大的解决方案来检查是否有任何进程正在运行(包括 BSD 进程),你可以执行以下操作:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/sysctl.h>
#include <sys/types.h>
int main(int argc, const char* argv[]) {
pid_t pid = atoi(argv[2]);
// This MIB array will get passed to sysctl()
// See man 3 sysctl for details
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
struct kinfo_proc result;
size_t oldp_len = sizeof(result);
// sysctl() refuses to fill the buffer if the PID does not exist,
// so the only way to detect failure is to set all fields to 0 upfront
memset(&result, 0, sizeof(struct kinfo_proc));
if (sysctl(name, 4, &result, &oldp_len, NULL, 0) < 0) {
perror("sysctl");
return 1;
}
// SZOMB means a zombie process, one that is still visible but is not running anymore
if (result.kp_proc.p_pid > 0 && result.kp_proc.p_stat != SZOMB) {
printf("Process is running.\n");
} else {
printf("Process is NOT running.\n");
}
return 0;
}
Note that the above code is a modified version of one of my private libraries and is untested. However, it should make clear how the API is used, and works successfully on macOS 10.14.5.
请注意,上面的代码是我的一个私有库的修改版本,未经测试。但是,应该明确 API 的使用方式,并在 macOS 10.14.5 上成功运行。