方法一: 用applescript获取
applescript在开发中也非常好用。
tell application "System Events"
set listOfProcesses to every process
set allProcess to {}
repeat with processItem in listOfProcesses
set procname to name of processItem as string
set processId to unix id of processItem as string
set processDic to {ProcessName:procname, processId:processId}
copy processDic to end of allProcess
end repeat
return allProcess
end tell
在项目中运行上述脚本,可获取到大部分正在运行中的Process,注意,是大部分,例如adb使用该方式获取不到,因此,继续探索其他方式。
方法二: 用ps ax
获取
可以通过ps命令获取,但是该方法需要自己解析,速度和效率较低,在此不适用。
方法三: 用GetBSDProcessList
获取
用GetBSDProcessList
函数(点我)可以获取到所有进程,但是在访问kinfo_proc
结构体的kp_proc.p_comm
时只有16位的长度。其定义如下:
#define MAXCOMLEN 16 //defined in param.h
struct extern_proc { //defined in proc.h
...snip...
char p_comm[MAXCOMLEN+1];
...snip...
};
方法四: 使用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
一样存在进程名显示不全的问题
方法五: 使用 ProcessManager 函数检索进程信息
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的应用程序,而且只针对当前用户。
方法六: 使用-[NSWorkspace launchedApplications]
只返回当前用户在Dock中出现的应用程序的信息。
方法七:虽然很简洁好用,但是OSX10.15beta中不管用的方法
#import <sys/proc_info.h>
#import <libproc.h>
int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
pid_t pids[numberOfProcesses];
bzero(pids, sizeof(pids));
proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
for (int i = 0; i < numberOfProcesses; ++i) {
if (pids[i] == 0) { continue; }
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
if (strlen(pathBuffer) > 0) {
printf("path: %s\n", pathBuffer);
}
}
这个方法很是管用,但是在OSX10.15beta系统中有问题,获取到的numberOfProcesses为0
方法八:终极解决办法,强烈建议使用!
#import <sys/sysctl.h>
#import <libproc.h>
- (NSArray *)runningProcesses {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
u_int miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = (int)(size / sizeof(struct kinfo_proc));
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
pid_t pid = process[i].kp_proc.p_pid;
NSString * processID = [[NSString alloc] initWithFormat:@"%d", pid];
NSString * processName = [self getProcessNameWithPid:pid];
if (processName.length > 0 && processID.length > 0) {
NSDictionary * dict = @{@"ProcessName" : processName, @"ProcessID" : processID };
[array addObject:dict];
}
}
free(process);
return [array copy];
}
}
}
return nil;
}
- (NSString *)getProcessNameWithPid:(pid_t)pid
{
NSString *processName = @"";
char pathBuffer [PROC_PIDPATHINFO_MAXSIZE];
proc_pidpath(pid, pathBuffer, sizeof(pathBuffer));
char nameBuffer[256];
int position = (int)strlen(pathBuffer);
while(position >= 0 && pathBuffer[position] != '/')
{
position--;
}
strcpy(nameBuffer, pathBuffer + position + 1);
processName = [NSString stringWithUTF8String:nameBuffer];
return processName;
}
该方法虽然稍显复杂,但是思路可做参考:它巧妙地通过processID,获取到该进程的路径path,然后截取路径path的lastComponent为其名称,进而获取到了进程名和id。
经过测试,该方法在OSX10.15beta中也可以正常获取到。
以上只是个人项目中所用总结,如有错误,恳请批评指正!如对您有帮助,点赞支持,谢谢!