Programmatically check if a process is running on Mac

psychotik picture psychotik · Mar 25, 2010 · Viewed 15.8k times · Source

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 goal is to check from code whether a process is running (by name).

Thanks!

Answer

valexa picture valexa · Sep 22, 2010

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;
}