以编程方式检查进程是否在Mac上运行

时间:2010-03-25 18:01:49

标签: cocoa macos unix macos-carbon

Mac上是否有可用于枚举进程的Carbon / Cocoa / C API?我在Windows上寻找像EnumProcesses这样的东西。

我的目标是从代码中检查进程是否正在运行(按名称)。

谢谢!

6 个答案:

答案 0 :(得分:15)

以下是一些具体的实现和细节,请注意proc-> kp_proc.p_comm有一个字符长度限制,这就是为什么我实现了infoForPID:而不是

可可:

[NSWorkspace launchApplications](10.2+,在10.7中弃用,非常有限的流程列表) [NSWorkspace runningApplications](10.6+,更少限制的进程列表,但仍不包括守护程序进程)

碳:

- (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 :(见Technical Q&A QA1123 Getting List of All Processes on 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;
}

答案 1 :(得分:9)

TechZen说: 截至2013年12月,流程管理器已完全弃用。

啊,我刚刚找到Process Manager reference

看起来GetNextProcessGetProcessInfo有助于弄清楚正在运行的内容。正如Dave所建议的那样,如果您正在寻找守护进程而不仅仅是碳/可可进程,则可以使用GetBSDProcessList

答案 2 :(得分:7)

有几种方法可以做到这一点:

  1. 如果它是带有Dock图标的GUI应用程序,请使用-[NSWorkspace launchedApplications]
  2. 通过NSTask分离另一个进程(如ps或top或其他),读取结果,然后搜索自己(或通过grep或其他东西管道)。
  3. 使用此处所述的GetBSDProcessList功能:http://developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html(我以前成功使用过此功能)

答案 3 :(得分:2)

NSRunningApplicationClass的概述中,它说:

  

NSRunningApplication是一个操作和提供应用程序单个实例信息的类。仅跟踪用户应用程序;这不提供有关系统上每个进程的信息。

  

要访问所有正在运行的应用程序的列表,请使用NSWorkspace中的runningApplications方法。

我建议您查看Workspace Services Programming Topics

答案 4 :(得分:1)

晚了聚会,但是如果您确实需要一个健壮的解决方案来检查任何进程(包括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;

}

请注意,以上代码是我的一个私有库的修改后的版本,未经测试。但是,应该明确API的使用方式,并在macOS 10.14.5上成功运行。

答案 5 :(得分:0)

您可以使用EndPointSecurity.framework,该版本自macOS 10.15起可用。有关更多信息,请参见Writing a Process Monitor with Apple's Endpoint Security Framework