MacOS develop - Get all the running process name and pid

Method One: Get with applescript

applescript in development is also very easy to use.

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

Run the above script in your project, you can get to most of the running Process, attention, in large part, for example, use the adb way to get less, therefore, continue to explore other ways.

Method 2: ps axacquired

Can be obtained by the ps command, but this method requires its own resolution, low speed and efficiency, this does not apply.

Method three: with GetBSDProcessListget

By GetBSDProcessListfunction ( points I can get) to all processes, but the access kinfo_procstructure kp_proc.p_commwhen only 16 bits long. Which is defined as follows:

#define MAXCOMLEN 16 //defined in param.h
struct extern_proc {  //defined in proc.h
  ...snip...
  char p_comm[MAXCOMLEN+1];
  ...snip...
};

Method 4: Use libProc.h get

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

Although the information is retrieved, however, and GetBSDProcessListthere is a problem of the same process name display incomplete

Method five: Use ProcessManager function to retrieve process information

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

Sorry, this approach does not work. It only returns the process registered in WindowServer (or something similar) in. In other words, it only returns the application with UI, but only for the current user.

Method six: Use-[NSWorkspace launchedApplications]

Only returns information about the current application user appears in the Dock.

Method 7: although very simple and easy to use, but regardless of the method used in 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);
    }
}

This method is very effective, but there are problems in OSX10.15beta system, acquired numberOfProcesses 0

Eight: the ultimate solution, it is strongly recommended!

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

This method, although somewhat complicated, but ideas do reference: it skillfully through processID, get to the path of the process path, then the path to intercept the path of lastComponent its name, and then get to the process name and id.
After testing, the method may also be acquired in normal OSX10.15beta.

These are just personal items used in the summary, if wrong, I implore criticism! If you have for your help, support thumbs up, thank you!

Reference material

Published 49 original articles · won praise 5 · views 20000 +

Guess you like

Origin blog.csdn.net/auspark/article/details/104441010