Как собрать системную информацию в OSX, используя цель C - PullRequest
6 голосов
/ 09 ноября 2009

Существует ли какой-либо метод / API, определенный для сбора системной информации в osx. Я хочу написать утилиту, которая будет собирать аппаратную информацию, такую ​​как процессор, RAM, сетевой адаптер. Любая идея ? Заранее спасибо.

Ответы [ 5 ]

12 голосов
/ 06 сентября 2012

System Profiler хорош и будет выводить XML для некоторого медленного файлового ввода-вывода, а также давайте зависим от другого процесса, который необходимо завершить, прежде чем получить нужную информацию. Хорошо, если я скажу это так, действительно ли System Profiler - лучший вариант и ответ на этот вопрос? Я думаю, что нет (ИМО).

Вот как я это делаю. Заголовок - это свойства только для чтения личных свойств чтения и записи. Методы категории довольно просты, но если у кого-то возникнут вопросы, напишите, и я отвечу.

#import <IOKit/IOKitLib.h>
#import <sys/sysctl.h>

@interface VarSystemInfo ()
@property (readwrite, strong, nonatomic) NSString *sysName;
@property (readwrite, strong, nonatomic) NSString *sysUserName;
@property (readwrite, strong, nonatomic) NSString *sysFullUserName;
@property (readwrite, strong, nonatomic) NSString *sysOSName;
@property (readwrite, strong, nonatomic) NSString *sysOSVersion;
@property (readwrite, strong, nonatomic) NSString *sysPhysicalMemory;
@property (readwrite, strong, nonatomic) NSString *sysSerialNumber;
@property (readwrite, strong, nonatomic) NSString *sysUUID;
@property (readwrite, strong, nonatomic) NSString *sysModelID;
@property (readwrite, strong, nonatomic) NSString *sysModelName;
@property (readwrite, strong, nonatomic) NSString *sysProcessorName;
@property (readwrite, strong, nonatomic) NSString *sysProcessorSpeed;
@property (readwrite, strong, nonatomic) NSNumber *sysProcessorCount;
@property (readonly,  strong, nonatomic) NSString *getOSVersionInfo;

- (NSString *) _strIORegistryEntry:(NSString *)registryKey;
- (NSString *) _strControlEntry:(NSString *)ctlKey;
- (NSNumber *) _numControlEntry:(NSString *)ctlKey;
- (NSString *) _modelNameFromID:(NSString *)modelID;
- (NSString *) _parseBrandName:(NSString *)brandName;
@end

static NSString* const kVarSysInfoVersionFormat  = @"%@.%@.%@ (%@)";
static NSString* const kVarSysInfoPlatformExpert = @"IOPlatformExpertDevice";

static NSString* const kVarSysInfoKeyOSVersion = @"kern.osrelease";
static NSString* const kVarSysInfoKeyOSBuild   = @"kern.osversion";
static NSString* const kVarSysInfoKeyModel     = @"hw.model";
static NSString* const kVarSysInfoKeyCPUCount  = @"hw.physicalcpu";
static NSString* const kVarSysInfoKeyCPUFreq   = @"hw.cpufrequency";
static NSString* const kVarSysInfoKeyCPUBrand  = @"machdep.cpu.brand_string";

static NSString* const kVarSysInfoMachineNames       = @"MachineNames";
static NSString* const kVarSysInfoMachineiMac        = @"iMac";
static NSString* const kVarSysInfoMachineMacmini     = @"Mac mini";
static NSString* const kVarSysInfoMachineMacBookAir  = @"MacBook Air";
static NSString* const kVarSysInfoMachineMacBookPro  = @"MacBook Pro";
static NSString* const kVarSysInfoMachineMacPro      = @"Mac Pro";

#pragma mark - Implementation:
#pragma mark -

@implementation VarSystemInfo

@synthesize sysName, sysUserName, sysFullUserName;
@synthesize sysOSName, sysOSVersion;
@synthesize sysPhysicalMemory;
@synthesize sysSerialNumber, sysUUID;
@synthesize sysModelID, sysModelName;
@synthesize sysProcessorName, sysProcessorSpeed, sysProcessorCount;

#pragma mark - Helper Methods:

- (NSString *) _strIORegistryEntry:(NSString *)registryKey {

    NSString *retString;

    io_service_t service =
    IOServiceGetMatchingService( kIOMasterPortDefault,
                                 IOServiceMatching([kVarSysInfoPlatformExpert UTF8String]) );
    if ( service ) {

        CFTypeRef cfRefString =
        IORegistryEntryCreateCFProperty( service,
                                         (__bridge CFStringRef)registryKey,
                                         kCFAllocatorDefault, kNilOptions );
        if ( cfRefString ) {

            retString = [NSString stringWithString:(__bridge NSString *)cfRefString];
            CFRelease(cfRefString);

        } IOObjectRelease( service );

    } return retString;
}

- (NSString *) _strControlEntry:(NSString *)ctlKey {

    size_t size = 0;
    if ( sysctlbyname([ctlKey UTF8String], NULL, &size, NULL, 0) == -1 ) return nil;

    char *machine = calloc( 1, size );

    sysctlbyname([ctlKey UTF8String], machine, &size, NULL, 0);
    NSString *ctlValue = [NSString stringWithCString:machine encoding:[NSString defaultCStringEncoding]];

    free(machine); return ctlValue;
}

- (NSNumber *) _numControlEntry:(NSString *)ctlKey {

    size_t size = sizeof( uint64_t ); uint64_t ctlValue = 0;
    if ( sysctlbyname([ctlKey UTF8String], &ctlValue, &size, NULL, 0) == -1 ) return nil;
    return [NSNumber numberWithUnsignedLongLong:ctlValue];
}

- (NSString *) _modelNameFromID:(NSString *)modelID {

    /*!
     * @discussion Maintain Machine Names plist from the following site
     * @abstract ref: http://www.everymac.com/systems/by_capability/mac-specs-by-machine-model-machine-id.html
     *
     * @discussion Also info found in SPMachineTypes.plist @ /System/Library/PrivateFrameworks/...
     *             ...AppleSystemInfo.framework/Versions/A/Resources
     *             Information here is private and can not be linked into the code.
     */

    NSDictionary *modelDict = [[NSBundle mainBundle] URLForResource:kVarSysInfoMachineNames withExtension:@"plist"].serialPList;
    NSString *modelName = [modelDict objectForKey:modelID];

    if ( !modelName ) {

        if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineiMac.lowercaseString] ) return kVarSysInfoMachineiMac;
        else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacmini.noWhitespaceAndLowerCaseString] )    return kVarSysInfoMachineMacmini;
        else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacBookAir.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacBookAir;
        else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacBookPro.noWhitespaceAndLowerCaseString] ) return kVarSysInfoMachineMacBookPro;
        else if ( [modelID.lowercaseString hasPrefix:kVarSysInfoMachineMacPro.noWhitespaceAndLowerCaseString] )     return kVarSysInfoMachineMacPro;
        else return modelID;

    } return modelName;
}

- (NSString *) _parseBrandName:(NSString *)brandName {

    if ( !brandName ) return nil;

    NSMutableArray *newWords = [NSMutableArray array];
    NSString *strCopyRight = @"r", *strTradeMark = @"tm", *strCPU = @"CPU";

    NSArray *words = [brandName componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]];

    for ( NSString *word in words ) {

        if ( [word isEqualToString:strCPU] )       break;
        if ( [word isEqualToString:@""] )          continue;
        if ( [word.lowercaseString isEqualToString:strCopyRight] ) continue;
        if ( [word.lowercaseString isEqualToString:strTradeMark] ) continue;

        if ( [word length] > 0 ) {

            NSString *firstChar = [word substringToIndex:1];
            if ( NSNotFound != [firstChar rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location ) continue;

            [newWords addObject:word];

    } } return [newWords componentsJoinedByString:@" "];
}

- (NSString *) getOSVersionInfo {

    NSString *darwinVer = [self _strControlEntry:kVarSysInfoKeyOSVersion];
    NSString *buildNo = [self _strControlEntry:kVarSysInfoKeyOSBuild];
    if ( !darwinVer || !buildNo ) return nil;

    NSString *majorVer = @"10", *minorVer = @"x", *bugFix = @"x";
    NSArray *darwinChunks = [darwinVer componentsSeparatedByCharactersInSet:[NSCharacterSet punctuationCharacterSet]];

    if ( [darwinChunks count] > 0 ) {

        NSInteger firstChunk = [(NSString *)[darwinChunks objectAtIndex:0] integerValue];
        minorVer = [NSString stringWithFormat:@"%ld", (firstChunk - 4)];
        bugFix = [darwinChunks objectAtIndex:1];
        return [NSString stringWithFormat:kVarSysInfoVersionFormat, majorVer, minorVer, bugFix, buildNo];

    } return nil;
}

#pragma mark - Initalization:

- (void) setupSystemInformation {

    NSProcessInfo *pi = [NSProcessInfo processInfo];

    self.sysName = [[NSHost currentHost] localizedName];
    self.sysUserName = NSUserName();
    self.sysFullUserName = NSFullUserName();
    self.sysOSName = pi.strOperatingSystem;
    self.sysOSVersion = self.getOSVersionInfo;
    self.sysPhysicalMemory = [[NSNumber numberWithUnsignedLongLong:pi.physicalMemory] strBinarySizeMaxFractionDigits:0];
    self.sysSerialNumber = [self _strIORegistryEntry:(__bridge NSString *)CFSTR(kIOPlatformSerialNumberKey)];
    self.sysUUID = [self _strIORegistryEntry:(__bridge NSString *)CFSTR(kIOPlatformUUIDKey)];
    self.sysModelID = [self _strControlEntry:kVarSysInfoKeyModel];
    self.sysModelName = [self _modelNameFromID:self.sysModelID];
    self.sysProcessorName = [self _parseBrandName:[self _strControlEntry:kVarSysInfoKeyCPUBrand]];
    self.sysProcessorSpeed = [[self _numControlEntry:kVarSysInfoKeyCPUFreq] strBaseTenSpeedMaxFractionDigits:2];
    self.sysProcessorCount = [self _numControlEntry:kVarSysInfoKeyCPUCount];
}

- (id) init {

    if ( (self = [super init]) ) {

        [self setupSystemInformation];

    } return self;
}

@end

Наслаждайтесь!

P.S. Я загружаю все значения свойств во время init, чтобы избежать нескольких системных вызовов &&, поскольку его дешевые && все значения должны быть довольно статичными.

P.P.S. Я также загружаю созданный мной список имен MachineNames, но я знаю, что это мой собственный процесс, который имеет к нему доступ, и в комментарии описывается, откуда я получаю информацию.

8 голосов
/ 09 ноября 2009

Самый простой способ - использовать вывод команды system_profiler . Он также имеет опцию -xml, чтобы упростить автоматический анализ вывода.

4 голосов
/ 10 ноября 2009

Базовый API, который, я полагаю, использует System Profiler (по крайней мере, для части информации, которую он собирает) и которую вы должны использовать, если вам нужна очень конкретная информация, - sysctl . Он позволяет запрашивать отдельные атрибуты системы, в том числе количество процессоров, скорость процессора, доступную память и т. Д.

1 голос
/ 09 ноября 2009

Для начала вам будет достаточно следующей ссылки:

Как получить аппаратную и сетевую конфигурацию

0 голосов
/ 09 ноября 2009

Вы можете использовать сценарий-мост в Leopard (или новее) для получения необходимой информации непосредственно из Apple System Profiler.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...