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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 06:50:02  来源:igfitidea点击:

Programmatically check if a process is running on Mac

cocoamacosunixmacos-carbon

提问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 EnumProcesseson Windows.

Mac 上是否有任何可用的 Carbon/Cocoa/C API 可用于枚举进程?我正在寻找类似EnumProcessesWindows 的东西。

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 GetNextProcessand GetProcessInfohelp in figuring out what's running. As suggested by Dave, GetBSDProcessListcan be used if you're looking for daemons and not just Carbon/Cocoa processes.

看起来GetNextProcessGetProcessInfo有助于找出正在运行的内容。正如 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:

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

  1. If it's a GUI app with a Dock icon, use -[NSWorkspace launchedApplications].
  2. 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).
  3. Use the GetBSDProcessListfunction described here: http://developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html(I've used this successfully in the past)
  1. 如果它是带有 Dock 图标的 GUI 应用程序,请使用-[NSWorkspace launchedApplications].
  2. 通过 an 分叉另一个进程(如 ps 或 top 或其他)NSTask,读取结果,并搜索自己(或通过 grep 或其他方式进行管道搜索)。
  3. 使用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 上成功运行。