Уникальный идентификатор оборудования в Mac OS X
Разработка для Mac OS X - это довольно новое животное для меня, и я нахожусь в процессе портирования некоторого программного обеспечения. Для лицензирования и регистрации программного обеспечения мне нужно иметь возможность генерировать какой-то идентификатор оборудования. Это не должно быть ничего фантастического; Ethernet MAC-адрес, последовательный жесткий диск, последовательный процессор, что-то в этом роде.
Я покрыл это на Windows, но я не имею понятия о Mac. Любая идея о том, что мне нужно сделать, или куда я могу обратиться за информацией об этом, была бы отличной!
Редактировать:
Для всех, кто заинтересован в этом, это код, который я в конечном итоге использовал с классом Qtcess Qt:
QProcess proc;
QStringList args;
args << "-c" << "ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { print $3; }'";
proc.start( "/bin/bash", args );
proc.waitForFinished();
QString uID = proc.readAll();
Примечание: я использую C++.
9 ответов
Попробуйте эту команду терминала:
ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s\n", line[4]); }'
Вот эта команда, обернутая в Какао (которая, возможно, могла бы быть немного более чистой):
NSArray * args = [NSArray arrayWithObjects:@"-rd1", @"-c", @"IOPlatformExpertDevice", @"|", @"grep", @"model", nil];
NSTask * task = [NSTask new];
[task setLaunchPath:@"/usr/sbin/ioreg"];
[task setArguments:args];
NSPipe * pipe = [NSPipe new];
[task setStandardOutput:pipe];
[task launch];
NSArray * args2 = [NSArray arrayWithObjects:@"/IOPlatformUUID/ { split($0, line, \"\\\"\"); printf(\"%s\\n\", line[4]); }", nil];
NSTask * task2 = [NSTask new];
[task2 setLaunchPath:@"/usr/bin/awk"];
[task2 setArguments:args2];
NSPipe * pipe2 = [NSPipe new];
[task2 setStandardInput:pipe];
[task2 setStandardOutput:pipe2];
NSFileHandle * fileHandle2 = [pipe2 fileHandleForReading];
[task2 launch];
NSData * data = [fileHandle2 readDataToEndOfFile];
NSString * uuid = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Для C/C++:
void get_platform_uuid(char * buf, int bufSize) {
io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
CFStringRef uuidCf = (CFStringRef) IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
IOObjectRelease(ioRegistryRoot);
CFStringGetCString(uuidCf, buf, bufSize, kCFStringEncodingMacRoman);
CFRelease(uuidCf);
}
Почему бы не попробовать gethostuuid()
? Вот документация из Руководства по системным вызовам Mac OS X:
НАЗВАНИЕ:
gethostuuid -- return a unique identifier for the current machine
СИНТАКСИС:
#include <unistd.h>
int gethostuuid(uuid_t id, const struct timespec *wait);
ОПИСАНИЕ:
Функция gethostuuid() возвращает 16-байтовый uuid_t, указанный в id, который однозначно идентифицирует текущий компьютер. Имейте в виду, что идентификаторы оборудования, которые gethostuuid() использует для генерации UUID, могут быть изменены сами.
Аргумент wait - это указатель на struct timespec, которая указывает максимальное время ожидания результата. Установка в ноль полей tv_sec и tv_nsec означает ожидание до тех пор, пока он не завершится.
ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ:
Функция gethostuuid() возвращает ноль в случае успеха или -1 в случае ошибки.
ОШИБКИ
Функция gethostuuid() завершается ошибкой, если:
[EFAULT] wait points to memory that is not a valid part of the
process address space.
[EWOULDBLOCK] The wait timeout expired before the UUID could be
obtained.
На это было бы легче ответить, если бы вы сказали нам, какой язык вы используете. Информация может быть получена без каких-либо команд оболочки через инфраструктуру SystemConfiguration, а также через IOKit, если вы хотите сильно испачкать руки.
- (NSString*) getMACAddress: (BOOL)stripColons {
NSMutableString *macAddress = nil;
NSArray *allInterfaces = (NSArray*)SCNetworkInterfaceCopyAll();
NSEnumerator *interfaceWalker = [allInterfaces objectEnumerator];
SCNetworkInterfaceRef curInterface = nil;
while ( curInterface = (SCNetworkInterfaceRef)[interfaceWalker nextObject] ) {
if ( [(NSString*)SCNetworkInterfaceGetBSDName(curInterface) isEqualToString:@"en0"] ) {
macAddress = [[(NSString*)SCNetworkInterfaceGetHardwareAddressString(curInterface) mutableCopy] autorelease];
if ( stripColons == YES ) {
[macAddress replaceOccurrencesOfString: @":" withString: @"" options: NSLiteralSearch range: NSMakeRange(0, [macAddress length])];
}
break;
}
}
return [[macAddress copy] autorelease];
}
/*
g++ mac_uuid.cpp -framework CoreFoundation -lIOKit
*/
#include <iostream>
#include <IOKit/IOKitLib.h>
using namespace std;
void get_platform_uuid(char * buf, int bufSize)
{
io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/");
CFStringRef uuidCf = (CFStringRef) IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
IOObjectRelease(ioRegistryRoot);
CFStringGetCString(uuidCf, buf, bufSize, kCFStringEncodingMacRoman);
CFRelease(uuidCf);
}
int main()
{
char buf[512] = "";
get_platform_uuid(buf, sizeof(buf));
cout << buf << endl;
}
Бег:
system_profiler | grep 'Serial Number (system)'
в терминале возвращает, что это, вероятно, уникальный идентификатор. Это работает на моем 10.5 боксе, я не уверен, какая правильная строка будет в других версиях OS X.
Как уже упоминали некоторые люди, вы можете использовать команду терминала для получения идентификатора оборудования.
Я предполагаю, что вы хотите сделать это в коде, поэтому я бы взглянул на класс NSTask в Какао. Это в основном позволяет вам запускать команды терминала внутри вашего приложения.
Этот код является примером того, как использовать NSTask в Какао. Он устанавливает среду для выполнения команды killall. Это передает его аргумент "Искатель".
Это эквивалентно запуску "killall Finder" в командной строке, что, очевидно, уничтожит Finder.
NSTask *aTask = [[NSTask alloc] init];
NSMutableArray *args = [NSMutableArray array];
[aTask setLaunchPath: @"/usr/bin/killall"];
[args addObject:[@"/Applications/Finder" lastPathComponent]];
[aTask setArguments:args];
[aTask launch];
[aTask release];
Следующая команда эквивалентна и намного проще, чем команда ioreg.
system_profiler SPHardwareDataType | awk '/UUID/ { print $3 }
Системный профилировщик (в Приложениях - Утилитах) содержит большую часть информации такого рода. Он имеет ваш серийный номер и ваш Mac-адрес (не имеет отношения к Mac. У всех компьютеров есть MAC-адрес, который в значительной степени уникален для каждой сетевой карты).