Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Jose Jayan

macrumors newbie
Original poster
Jun 9, 2009
7
0
Hi there

I want to write a cocoa app which will retrieve the following machine details.

CPU Model,CPU ID
Machine Name, Machine IP
Hard Disk Details
RAM Details
Operating System


Could you people please advice me on this(Instead of calling system_profiler from terminal)?
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
There is no Cocoa API for this. You have to call into Carbon (if you can find an API for it: I haven't looked) or do what you have already ruled out: call out to the system_profiler command line.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
Hi there

I want to write a cocoa app which will retrieve the following machine details.

CPU Model,CPU ID
Machine Name, Machine IP
Hard Disk Details
RAM Details
Operating System


Could you people please advice me on this(Instead of calling system_profiler from terminal)?

Search for "Gestalt".
Or use the power of Posix to call system_profiler from your application and read its output.
 

Jose Jayan

macrumors newbie
Original poster
Jun 9, 2009
7
0
Search for "Gestalt".
Or use the power of Posix to call system_profiler from your application and read its output.

But neither the Gestalt or system_profiler revealed the CPU Serial ID or MotherBoardID(Serial Number).
Also tried IOREG from terminal.
 

Guiyon

macrumors 6502a
Mar 19, 2008
771
4
Cambridge, MA
Depending on exactly what you need, you have several options other than relying on a dying API or brute-force searching through the output of an NSTask. For example, both the NSProcessInfo and the sysctl API can provide a significant amount of information about a system (and, in the case of sysctl, it's pretty portable). If you need even more detailed information there is also IOKit and, using that, you can grab everything down to each individual CPU's ID.

Just the file as "HWInfo.m" and compile it using:
Code:
gcc -framework "Foundation" -framework "IOKit" -o HWInfo HWInfo.m


Edit: Updated with code for grabbing CPUIDs and Serial Number using IOKit
Edit 2: Significantly condensed down the code for grabbing the serial number. It's just grabbing the root entry so setting up a matching dictionary, etc. is just overkill.
Edit 3: Last edit, I promise! Moved the sysctl stuff into its own function to make it a bit easier to parse. Replaced NSLog with objc_println.

Here is an example using NSProcessInfo, sysctl and the IOKit APIs:
Code:
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>

#include <sys/sysctl.h>
#include <sys/resource.h>
#include <sys/vm.h>

static void objc_println( NSString* format, ... );
static void printSysctlInfo( void );
static NSDictionary* getCpuIds( void );
static NSString* getPlatformSerialNumber( void );

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  
  objc_println(@"Beginning system data collection...");
  
  NSProcessInfo* pinfo = [NSProcessInfo processInfo];
  
  objc_println( @"NSProcessInfo:" );
  objc_println( @"\tProcess Name: %@", [pinfo processName] );
  objc_println( @"\tPID: %d", [pinfo processIdentifier] );
  objc_println( @"\tProcess GUID: %@", [pinfo globallyUniqueString] );
  objc_println( @"\tOS Version: %@", [pinfo operatingSystemVersionString] );
  objc_println( @"\tTotal Processors: %d", [pinfo processorCount] );
  objc_println( @"\tActive Processors: %d", [pinfo activeProcessorCount] );
  objc_println( @"\tTotal RAM: %ull bytes", [pinfo physicalMemory] );
  
  printSysctlInfo();
  
  objc_println( @"IOKit:" );
  NSDictionary *cpuInfo = getCpuIds();
  NSArray* keys = [[cpuInfo allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
  
  for( id key in keys ) {
    objc_println( @"\t%@ has ID: 0x%8.8x", key, [(NSNumber*)[cpuInfo objectForKey: key] unsignedIntValue] );
  }
  
  objc_println( @"\tSerial Number: %@", getPlatformSerialNumber() );
  
  [pool drain];
  
  return 0;
}

static void objc_println( NSString* format, ... ) {
  va_list args;

  if (![format hasSuffix: @"\n"]) {
    format = [format stringByAppendingString: @"\n"];
  }
	
  va_start (args, format);
  NSString *body =  [[NSString alloc] initWithFormat: format
                                           arguments: args];
  va_end (args);
	
  fprintf(stderr,"%s",[body UTF8String]);
  
  [body release];
}

static void printSysctlInfo( void ) {
  objc_println( @"sysctl:" );
  
  int mib[2];
  size_t len = 0;
  char *rstring = NULL;
  unsigned int rint = 0;
  
  /* Setup the MIB data */
  mib[0] = CTL_KERN;
  mib[1] = KERN_OSTYPE;
  
  /* Get the length of the string */
  sysctl( mib, 2, NULL, &len, NULL, 0 );
  
  /* Now allocate space for the string and grab it */
  rstring = malloc( len );
  sysctl( mib, 2, rstring, &len, NULL, 0 );
  objc_println( @"\tkern.ostype: %s", rstring );
  
  /* Make sure we clean up afterwards! */
  free( rstring );
  rstring = NULL;
  
  /* Get the kernel release number */
  mib[0] = CTL_KERN;
  mib[1] = KERN_OSRELEASE;
  sysctl( mib, 2, NULL, &len, NULL, 0 );
  rstring = malloc( len );
  sysctl( mib, 2, rstring, &len, NULL, 0 );
  objc_println( @"\tkern.osrelease: %s", rstring );
  free( rstring );
  rstring = NULL;
  
  /* Get the Mac OS X Build number */
  mib[0] = CTL_KERN;
  mib[1] = KERN_OSVERSION;
  sysctl( mib, 2, NULL, &len, NULL, 0 );
  rstring = malloc( len );
  sysctl( mib, 2, rstring, &len, NULL, 0 );
  objc_println( @"\tkern.osversion: %s", rstring );
  free( rstring );
  rstring = NULL;
  
  mib[0] = CTL_HW;
  mib[1] = HW_MODEL;
  sysctl( mib, 2, NULL, &len, NULL, 0 );
  rstring = malloc( len );
  sysctl( mib, 2, rstring, &len, NULL, 0 );
  objc_println( @"\thw.model: %s", rstring );
  free( rstring );
  rstring = NULL;
  
  sysctlbyname( "machdep.cpu.brand_string", NULL, &len, NULL, 0 );
  rstring = malloc( len );
  sysctlbyname( "machdep.cpu.brand_string", rstring, &len, NULL, 0 );
  objc_println( @"\tmachdep.cpu.brand_string: %s", rstring );
  free( rstring );
  rstring = NULL;
  
  mib[0] = CTL_HW;
  mib[1] = HW_CPU_FREQ;
  len = sizeof( rint );
  sysctl( mib, 2, &rint, &len, NULL, 0 );
  objc_println( @"\thw.cpufrequency: %u", rint );
}

static NSString* getPlatformSerialNumber( void ) {
  io_registry_entry_t     rootEntry = IORegistryEntryFromPath( kIOMasterPortDefault, "IOService:/" );
  CFTypeRef serialAsCFString = NULL;
  
  serialAsCFString = IORegistryEntryCreateCFProperty( rootEntry,
                                                     CFSTR(kIOPlatformSerialNumberKey),
                                                     kCFAllocatorDefault,
                                                     0);

  IOObjectRelease( rootEntry );
  return (NULL != serialAsCFString) ? [(NSString*)serialAsCFString autorelease] : nil;
}

static NSDictionary* getCpuIds( void ) {
  NSMutableDictionary*    cpuInfo = [[NSMutableDictionary alloc] init];
  CFMutableDictionaryRef  matchClasses = NULL;
  kern_return_t           kernResult = KERN_FAILURE;
  mach_port_t             machPort;
  io_iterator_t           serviceIterator;
  
  io_object_t             cpuService;
  
  kernResult = IOMasterPort( MACH_PORT_NULL, &machPort );
  if( KERN_SUCCESS != kernResult ) {
    printf( "IOMasterPort failed: %d\n", kernResult );
  }
  
  matchClasses = IOServiceNameMatching( "processor" );
  if( NULL == matchClasses ) {
    printf( "IOServiceMatching returned a NULL dictionary" );
  }
  
  kernResult = IOServiceGetMatchingServices( machPort, matchClasses, &serviceIterator );
  if( KERN_SUCCESS != kernResult ) {
    printf( "IOServiceGetMatchingServices failed: %d\n", kernResult );
  }
  
  while( (cpuService = IOIteratorNext( serviceIterator )) ) {
    CFTypeRef CPUIDAsCFNumber = NULL;
    io_name_t nameString;      
    IORegistryEntryGetNameInPlane( cpuService, kIOServicePlane, nameString );
    
    CPUIDAsCFNumber = IORegistryEntrySearchCFProperty( cpuService, 
                                                      kIOServicePlane,
                                                      CFSTR( "IOCPUID" ), 
                                                      kCFAllocatorDefault,
                                                      kIORegistryIterateRecursively);
    
    if( NULL != CPUIDAsCFNumber ) {
      NSString* cpuName = [NSString stringWithCString:nameString];
      [cpuInfo setObject:(NSNumber*)CPUIDAsCFNumber forKey:cpuName];
    }
    
    if( NULL != CPUIDAsCFNumber ) {
      CFRelease( CPUIDAsCFNumber );
    }
  }
  
  IOObjectRelease( serviceIterator );
  
  return [cpuInfo autorelease];
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.