Mac OS X 开发对我来说是一个相当新的领域,我正在移植一些软件。对于软件许可和注册,我需要能够生成某种硬件 ID。它不必是任何花哨的东西;以太网 MAC 地址、硬盘序列号、CPU 序列号等。
我已经在 Windows 上了解了它,但在 Mac 上我没有任何线索。如果我知道我需要做什么,或者我可以去哪里获取这方面的信息,那就太棒了!
编辑:
对于对此感兴趣的其他人,这是我最终在 Qt 的 QProcess 类中使用的代码:
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++。
对于 C/C++:
#include <IOKit/IOKitLib.h>
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);
}
尝试这个终端命令:
ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s\n", line[4]); }'
从这里
这是用 Cocoa 封装的命令(可能可以做得更干净一些):
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];
为什么不尝试
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() 函数返回 id 指定的 16 字节 uuid_t,唯一标识当前机器。 请注意,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.
如果您告诉我们您使用的是什么语言,这个问题会更容易回答。这些信息无需任何 shell 命令即可通过 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)'
在终端中返回可能是唯一的 ID。这适用于我的 10.5 机器,我不确定其他版本的 OS X 中正确的字符串是什么。
正如上面一些人所暗示的,您可以使用终端命令来获取硬件ID。
我假设你想在代码中执行此操作,所以我会看一下 Cocoa 中的 NSTask 类。它基本上可以让您在应用程序内运行终端命令。
这段代码是如何在 Cocoa 中使用 NSTask 的示例。它设置执行“killall”命令的环境。它传递给它的参数“Finder”。
相当于在命令行中运行“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 地址,对于每个网卡来说几乎都是唯一的)。