Programmatically retrieving System Information on MAC

Let us first see how to view system information on Mac manually
To find the Mac OS version and memory information, go to the Apple menu and choose “About This Mac”.

2

The About This Mac window should look similar to this:

2

System Profiler :

OS X includes a utility called “System Profiler” that provides more advanced information about the system. In the About This Mac window, click the More Info button to open System Profiler.

As soon as you click “more info” button you will see system profiler utility window as shown below:

System Info

This was the manual process to get the information, but what in case you need to create an application which wants to access any of this information for ex. Mac address, HardwareUUID etc.
To accomplish this we will use system profiler shell command to extract all this information programmatically from the system.
Detailed description of System profiler shell command(necessary to understand code ahead)

system_profiler
Syntax:
system_profiler [-Options or Type(s)]
Usage/Explanation:
Give detailed information about your Mac including the hardware.
Options
-detailLevel <lvl>         //Decide how detailed the description will be. <lvl> can be mini, basic or full.

-listDataTypes            //Displays all available categories (as specified below).

Categories

Below is a list of all available information categories you can choose to retrieve.

• SPHardwareDataType
• SPNetworkDataType
• SPSoftwareDataType
• SPParallelATADataType
• SPAudioDataType
• SPBluetoothDataType
• SPDiagnosticsDataType
• SPDiscBurningDataType
• SPEthernetDataType
• SPFibreChannelDataType
• SPFireWireDataType
• SPDisplaysDataType
• SPHardwareRAIDDataType
• SPMemoryDataType
• SPPCIDataType
• SPParallelSCSIDataType
• SPPowerDataType
• SPPrintersDataType
• SPSASDataType
• SPSerialATADataType
• SPUSBDataType
• SPAirPortDataType
• SPFirewallDataType
• SPNetworkLocationDataType
• SPModemDataType
• SPNetworkVolumeDataType
• SPWWANDataType
• SPApplicationsDataType
• SPDeveloperToolsDataType
• SPExtensionsDataType
• SPFontsDataType
• SPFrameworksDataType
• SPLogsDataType
• SPManagedClientDataType
• SPPrefPaneDataType
• SPStartupItemDataType
• SPSyncServicesDataType
• SPUniversalAccessDataType

Example
system_profiler                                         //Displays information about your Mac computer (standard level)
system_profiler -detailLevel mini   //Displays a minimal summary of your system information.

//Only display information from the category SPHardwareDataType and SPNetworkDataType.

system_profiler SPHardwareDataType SPNetworkDataType

Following code demonstrates the use of the system_profiler shell command and how it can be called by a Core Foundation application to retrieve the same information that is displayed in the System Profiler utility.
Here we are using UNIX popen call to open a stream and read the results of the system_profiler command. The resultant data is then read into a buffer and converted to a CFArray using the CFPropertyListCreateFromXMLData call.

For this example, I have parsed the CFArray for specific Hardware information

// Returns the CFDictionary that contains the system profiler data type described in inDataType.
CFDictionaryRef FindDictionaryForDataType (const CFArrayRef inArray, CFStringRef inDataType)
{
UInt8   i;
CFDictionaryRef theDictionary;

// Search the array of dictionaries for a CFDictionary that matches
for (i = 0; i<CFArrayGetCount(inArray); i++)
{
theDictionary = CFArrayGetValueAtIndex(inArray, i);

// If the CFDictionary at this index has a key/value pair with the value equal to inDataType, retain and return it.
if (CFDictionaryContainsValue (theDictionary, inDataType))
{
// Retain the dictionary.  Caller is responsible for releasing it.
CFRetain (theDictionary);
return (theDictionary);
}
}

return (NULL);
}

// Returns the CFArray of “item” dictionaries.
CFArrayRef GetItemsArrayFromDictionary (const CFDictionaryRef inDictionary)
{
CFArrayRef  itemsArray;

// Retrieve the CFDictionary that has a key/value pair with the key equal to “_items”.
itemsArray = CFDictionaryGetValue (inDictionary, CFSTR(“_items”));
if (itemsArray != NULL)
CFRetain (itemsArray);

return (itemsArray);
}

– (void)retrieveSystemProfilerInformation

{

FILE *sys_profile;

size_t bytesRead = 0;

char streamBuffer[1024*512];

UInt8 i = 0;

CFDataRef xmlData;

CFDictionaryRef hwInfoDict;

CFArrayRef itemsArray;

CFIndex arrayCount;

// popen will fork and invoke the system_profiler command and return a stream reference with its result data

sys_profile = popen(“system_profiler SPHardwareDataType -xml”, “r”);

// Read the stream into a memory buffer

bytesRead = fread(streamBuffer, sizeof(char), sizeof(streamBuffer), sys_profile);

// Close the stream

pclose (sys_profile);

// Create a CFDataRef with the xml data

xmlData = CFDataCreate (kCFAllocatorDefault, (UInt8 *)streamBuffer, bytesRead);

// CFPropertyListCreateFromXMLData reads in the XML data and will parse it into a CFArrayRef for us.

CFStringRef errorString;

CFArrayRef propertyArray = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, xmlData, kCFPropertyListImmutable, &errorString);

// This will be the dictionary that contains all the Hardware information that system_profiler knows about.

hwInfoDict = FindDictionaryForDataType (propertyArray, CFSTR(“SPHardwareDataType”));

if (hwInfoDict!= NULL)

{

itemsArray = GetItemsArrayFromDictionary (hwInfoDict);

if (itemsArray != NULL)

{

// Find out how many items in this category – each one is a dictionary

arrayCount = CFArrayGetCount (itemsArray);

for (i=0; i < arrayCount; i++)

{

CFMutableStringRef outputString;

// Create a mutable CFStringRef with the dictionary value found with key “machine_name”

// This is the machine_name of this mac machine.

// Here you can give any value in key tag,to get its corresponding content

outputString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFDictionaryGetValue (CFArrayGetValueAtIndex(itemsArray, i), CFSTR(“machine_model”)));

//your code here

//(you can append output string OR modify your function according to your need )

CFRelease (outputString);

}

CFRelease (itemsArray);

}

CFRelease (hwInfoDict);

}

}

Here we have used only “SPHardwareDataType“,which is one of the category of system information. Similarly you can use any of the category as described above and modify the function according to your need.
XML structure created by system_profiler command (FOR REFERENCE):

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”&gt;
<plist version=”1.0″>
<array>
<dict>
<key>_dataType</key>
<string>SPHardwareDataType</string>
<key>_detailLevel</key>
<string>-2</string>
<key>_items</key>
<array>
<dict>
<key>SMC_version_system</key>
<string>1.65f2</string>
<key>_name</key>
<string>hardware_overview</string>
<key>boot_rom_version</key>
<string>MM41.0042.B00</string>
<key>bus_speed</key>
<string>1.07 GHz</string>
<key>cpu_type</key>
<string>Intel Core 2 Duo</string>
<key>current_processor_speed</key>
<string>2.4 GHz</string>
<key>l2_cache</key>
<string>3 MB</string>
<key>machine_model</key>
<string>Macmini4,1</string>
<key>machine_name</key>
<string>Mac mini</string>
<key>number_processors</key>
<integer>2</integer>
<key>packages</key>
<integer>1</integer>
<key>physical_memory</key>
<string>2 GB</string>
<key>platform_UUID</key>
<string>A7FF56CA-BDF7-5F54-88E3-6B2A7FFC308E</string>
<key>serial_number</key>
<string>C07CXTA7DD6H</string>
</dict>
</array>
<key>_properties</key>
<dict>

Written By: HEM DUTT, Sr. Engineer/Tech Lead (Mac OSX development), Mindfire Solutions

Advertisements

About HEM DUTT

Seasoned Mac OS X developer. Expertise in Mac OSX application development. knowledge of MFC and IOS

Posted on January 24, 2014, in Core Foundation and tagged , , , , , , . Bookmark the permalink. 4 Comments.

  1. Where are defined the functions “FindDictionaryForDataType” and “GetItemsArrayFromDictionary”? What library do I have to include?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

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

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s

%d bloggers like this: