Programmatically check if a process is running on Mac

前端 未结 6 1368
伪装坚强ぢ
伪装坚强ぢ 2020-12-01 02:06

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.

My go

相关标签:
6条回答
  • 2020-12-01 02:46

    You might use EndPointSecurity.framework which is available since macOS 10.15. Refer to Writing a Process Monitor with Apple's Endpoint Security Framework for more information

    0 讨论(0)
  • 2020-12-01 02:49

    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

    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)

    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 )

    - (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;
    }
    
    0 讨论(0)
  • 2020-12-01 02:53

    Late to the party, but if you really need a robust solution that can check whether any process is running (including BSD processes), you can do the following:

    
    #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.

    0 讨论(0)
  • 2020-12-01 02:54

    In the overview of the NSRunningApplicationClass, it says:

    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.

    and

    To access the list of all running applications, use the runningApplications method in NSWorkspace.

    I would suggest taking a look at Workspace Services Programming Topics

    0 讨论(0)
  • 2020-12-01 02:59

    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 GetBSDProcessList function described here: http://developer.apple.com/legacy/mac/library/#qa/qa2001/qa1123.html (I've used this successfully in the past)
    0 讨论(0)
  • 2020-12-01 03:12

    TechZen says: The Process Manager is, as of Dec 2013, completely deprecated.

    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.

    0 讨论(0)
提交回复
热议问题