Как System Profiler извлекает полный идентификатор оборудования Mac?

Существует несколько команд терминала для получения числового/сокращенного идентификатора модели для оборудования Mac.

  • sysctl hw.model
  • system_profiler SPHardwareDataType

Они выводят строку с именем оборудования и версией x, y. В настоящее время нам необходимо вести таблицу для преобразования этих идентификаторов в полное описание машины на английском языке.

Существует ли API или, что лучше, инструмент командной строки, который может создавать более понятные для человека имена, соответствующие документации Apple MacBook Pro 15-дюймовый, середина 2009 года или MacBook Pro (13-дюймовый, 2016 год, Четыре порта Thunderbolt 3) вместо более сокращенного MacBookPro5,3 или MacBookPro13,2 Идентификатор модели?

MacBookPro5,3 MacBookPro13,2

Подводя итог, как System Profiler получает полные локализованные имена оборудования Macintosh таким образом, который я могу генерировать для систематического использования этой информации с помощью скрипта или программы?

Ответы

Ответ 1

Нет необходимости в веб-запросах, чтобы получить эту информацию.

Текущую модель, как это показано в Об этом Mac, можно получить из:

~/Library/Preferences/com.apple.SystemProfiler.plist

Список содержит имена локализованных на добавленных языках текущих пользователей:

<?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">
<plist version="1.0">
<dict>
    <key>GTF1-sv-SE_SE</key>
    <string>MacBook Pro (15 tum, 2016)</string>
    <key>GTF1-en-SE_SE</key>
    <string>MacBook Pro (15-inch, 2016)</string>
</dict>
</plist>

Где ключи - это просто последние 4 буквы серийного номера (GTF1), за которыми следует локаль.

Если вы хотите, вы можете даже отредактировать этот список, чтобы настроить окно "Об этом Mac", что является обычной практикой среди пользователей Hackintosh.

EDIT:

Полная реализация в Swift 5:

public enum SystemInfo {

    public static var serialNumber: String? {
        let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"))
        return IORegistryEntryCreateCFProperty(service, "IOPlatformSerialNumber" as CFString, kCFAllocatorDefault, 0).takeUnretainedValue() as? String
    }

    public static var modelName: String? {
        guard let serial = serialNumber,
            let plist = try? PropertyList.load(from: .init(fileURLWithPath: "\(NSHomeDirectory())/Library/Preferences/com.apple.SystemProfiler.plist")),
            let regionCode = Locale.current.regionCode,
            let names = plist["CPU Names"] as? [String: String],
            !names.isEmpty else {
                return nil
        }
        for language in Locale.preferredLanguages {
            let key = "\(serial.suffix(4))-\(language)_\(regionCode)"
            if let entry = names[key] {
                return entry
            }
        }
        return nil
    }

}

Где я также использую это вспомогательное перечисление:

public enum PropertyList {

    public static func load(from url: URL) throws -> [String: Any]? {
        guard let plist = FileManager.default.contents(atPath: url.path) else { return nil }
        var format = PropertyListSerialization.PropertyListFormat.xml
        return try PropertyListSerialization.propertyList(from: plist, options: .mutableContainersAndLeaves, format: &format) as? [String: Any]
    }

    public static func save(_ plist: [String: Any], to url: URL) throws {
        let data = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)
        try data.write(to: url, options: .atomic)
    }

}

Использование:

print(SystemInfo.modelName)

Возвращает (шведский):

MacBook Pro (15 tum, 2016)

Ответ 3

ServerKit.framework имеет список свойств в своих ресурсах, который может помочь вам с преобразованием строки имени модели ↔ :

/System/Library/PrivateFrameworks/ServerKit.framework/Versions/A/Resources/English.lproj/XSMachineAttributes.plist

Ответ 4

Вы можете использовать system_profiler -xml SPHardwareDataType и искать ключ machine_name.

РЕДАКТИРОВАТЬ: Конечно, это не отвечает на вопрос в заголовке того, как это делает System Profiler, но предоставляет способ сделать это в вашем собственном коде.