A simple Objective-C class for checking if a specific process is running

DO NOT USE  THIS INTERFACE IN YOUR PRODUCTION CODE. 
ALTHOUGH I UPDATED IT, IT’S OUT-OF-DATE AND APPLE PROVIDES A METHOD FOR DOING THE SAME THING. DON’T TRY TO REINVENT WHEELS.

THIS WAS WRITTEN WHEN THERE WAS NO 64BIT CODING WIDELY AVAILABLE AND NSUInteger AND NSInteger WERE BEING INTRODUCED AFTER I WROTE THIS POST.

FOR EASIER MIGRATION BETWEEN 32 BIT AND 64 BIT, AVOID USING OPAQUE TYPE DIRECTLY. TRY TO USE TYPES LIKE NSUInteger AND NSInteger, FOR EXAMPLE.

The Cocoa doesn’t seem to provide an easy way to check if a process you wanted to check is rurning.
So, I wrote a simple Objective-C class for that purpose.

(If you have some great idea how to get absolute paths for running processes, please tell me.  I’d like to add the feature to this class.)

Source 1 : JAProcessInfo.h


#import <Cocoa/Cocoa.h>

@interface JAProcessInfo : NSObject {

@private
    int numberOfProcesses;
    NSMutableArray *processList;
}
- (id) init;
- (int)numberOfProcesses;
- (void)obtainFreshProcessList;
- (BOOL)findProcessWithName:(NSString *)procNameToSearch;
 @end

Source 2 : JAProcessInfo.m


#import "JAProcessInfo.h"

#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <sys/sysctl.h>

typedef struct kinfo_proc kinfo_proc;

@implementation JAProcessInfo
- (id) init
{
    self = [super init];

    if (self != nil)
    {
        numberOfProcesses = -1; // means "not initialized"
        processList = NULL;
    }

    return self;
}

- (int)numberOfProcesses
{
    return numberOfProcesses;
}

- (void)setNumberOfProcesses:(int)num
{
    numberOfProcesses = num;
}

- (int)getBSDProcessList:(kinfo_proc **)procList
   withNumberOfProcesses:(size_t *)procCount
{
    int             err;
    kinfo_proc *    result;
    bool            done;
    static const int    name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
    size_t          length;

    // a valid pointer procList holder should be passed
    assert( procList != NULL );
    // But it should not be pre-allocated
    assert( *procList == NULL );
    // a valid pointer to procCount should be passed
    assert( procCount != NULL );

    *procCount = 0;

    result = NULL;
    done = false;

    do
    {
        assert( result == NULL );

        // Call sysctl with a NULL buffer to get proper length
        length = 0;
        err = sysctl((int *)name,(sizeof(name)/sizeof(*name))-1,NULL,&length,NULL,0);
        if( err == -1 )
            err = errno;

        // Now, proper length is optained
        if( err == 0 )
        {
            result = malloc(length);
            if( result == NULL )
                err = ENOMEM;   // not allocated
        }

        if( err == 0 )
        {
            err = sysctl( (int *)name, (sizeof(name)/sizeof(*name))-1, result, &length, NULL, 0);
            if( err == -1 )
                err = errno;

            if( err == 0 )
                done = true;
            else if( err == ENOMEM )
            {
                assert( result != NULL );
                free( result );
                result = NULL;
                err = 0;
            }
        }
    }while ( err == 0 && !done );

    // Clean up and establish post condition
    if( err != 0 && result != NULL )
    {
        free(result);
        result = NULL;
    }

    *procList = result; // will return the result as procList
    if( err == 0 )
        *procCount = length / sizeof( kinfo_proc );

    assert( (err == 0) == (*procList != NULL ) );

    return err;
}

- (void)obtainFreshProcessList
{
    int i;
    kinfo_proc *allProcs = 0;
    size_t numProcs;
    NSString *procName;

    int err =  [self getBSDProcessList:&allProcs withNumberOfProcesses:&numProcs];
    if( err )
    {
        numberOfProcesses = -1;
        processList = NULL;

        return;
    }

    // Construct an array for ( process name )
    processList = [NSMutableArray arrayWithCapacity:numProcs];
    for( i = 0; i < numProcs; i++ )
    {
        procName = [NSString stringWithFormat:@"%s", allProcs[i].kp_proc.p_comm];
        [processList addObject:procName];
    }

    [self setNumberOfProcesses:numProcs];

    // NSLog(@"# of elements = %d total # of process = %d\n",
    //         [processArray count], numProcs );

    free( allProcs );

}

- (BOOL)findProcessWithName:(NSString *)procNameToSearch
{
    NSUInteger index;

    index = [processList indexOfObject:procNameToSearch];

    if( index == NSNotFound )
        return NO;
    else
        return YES;
}
@end

How to use it?

JAProcessInfo *procInfo = [[JAProcessInfo alloc] init];

    [procInfo obtainFreshProcessList]; // Get a list of process
    BOOL isRunning = [procInfo findProcessWithName:@"mlnet"];
About these ads

20 responses to this post.

  1. This doesn’t seem to be working for me. The process I specifiy isn’t open, but this class is reporting that it is. I have a helper app in my project (command line tool), that I made sure to shut down in Activity Monitor for testing purposes. I then ran the check and it said it was open anyway. Any reasons why?

    Reply

    • Posted by jongampark on May 24, 2012 at 3:16 PM

      Probably something in Mac OS X is changed since I wrote that. I received comments from others saying that it worked.
      I don’t know your environment and your source codes, so I can’t guess anything. But here is a good news. You don’t need the code over there anymore.

      There are other stuffs which were written after the code in this post was written. ( The code is not fully originated from me. It was in Apple’s sample code. But at that time, it was very hard to find one. So, I have to either make a task for “ps” command, but making synchronous behavior sure was an issue. But at that time, I found the code. )
      One is “launchedApplications” in NSWorkspace. (Welcome. this is one of the lowest AppKit class which is supposed to provide OSapp information. ) However, it says that it is deprecated since 10.7.
      When Apple deprecates something, it means they prepared a better one as one or more classes. Unlike MS, they tend to monitor what developer community wants and provide those. Yeah.. since the iOS, lots of people at Apple who used to work in Mac team has been moved to iOS team and such support has been diminished. But.. still it is how it is or should be.

      So.. there is a new message, runningApplications in NSWorkspace and that is said to return an array of instances of NSRunningApplication class. So, you will get more information about running processes there.
      I believe it’s the one you are looking for and going to rely on.

      Happy coding!!! :)

      Reply

  2. In fact, I can pass absolutely any string as the process and it says it’s open…

    Reply

  3. Simply apply the following changes and everything works well..

    – (BOOL)findProcessWithName:(NSString *)procNameToSearch
    {
    return [processList containsObject:procNameToSearch];
    }

    Reply

    • Posted by jongampark on June 15, 2012 at 8:15 PM

      So, sounds like indexOfObject is kind of deprecated.

      But why are there so many people who still try to use this? Do you guys need to support old Mac OS X?

      Reply

  4. Posted by SergiyM on August 27, 2012 at 6:18 PM

    In findProcessWithName method, the “index” variable is declared as int (32 bit long). Later it get’s compared with NSNotFound, which is equal to LONG_MAX. That’s why the result of such comparison is always FALSE — int index has not enough bits to be compared to long value. So, what ever name of process you are passing to method, the result will be YES. Declare “index” as long.

    Reply

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 47 other followers

%d bloggers like this: