独特的硬件ID在Mac OS X。

时间:2023-01-26 16:44:06

Mac OS X development is a fairly new animal for me, and I'm in the process of porting over some software. For software licensing and registration I need to be able to generate some kind of hardware ID. It doesn't have to be anything fancy; Ethernet MAC address, hard drive serial, CPU serial, something like that.

Mac OS X开发对我来说是一种全新的动物,我正在移植一些软件。对于软件许可和注册,我需要能够生成某种硬件ID,它不需要任何花哨的东西;以太网MAC地址,硬盘串行,CPU串行,诸如此类。

I've got it covered on Windows, but I haven't a clue on Mac. Any idea of what I need to do, or where I can go for information on this would be great!

我已经把它覆盖在Windows上了,但是我在Mac上没有任何线索。任何关于我需要做什么,或者我可以去哪里获取信息的想法都很好!

Edit:

编辑:

For anybody else that is interested in this, this is the code I ended up using with Qt's QProcess class:

对于其他感兴趣的人,这是我使用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();

Note: I'm using C++.

注意:我使用c++。

8 个解决方案

#1


14  

Try this Terminal command:

试试这个终端命令:

ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s\n", line[4]); }'

From here

从这里

Here is that command wrapped in Cocoa (which could probably be made a bit cleaner):

下面是用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];

#2


31  

For C/C++:

对于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);    
}

#3


7  

Why not try gethostuuid()? Here's the documentation from the Mac OS X System Calls Manual:

为什么不试试gethostuuid()?以下是Mac OS X系统调用手册的文档:

NAME:

名称:

 gethostuuid -- return a unique identifier for the current machine

SYNOPSIS:

剧情简介:

 #include <unistd.h>

 int gethostuuid(uuid_t id, const struct timespec *wait);

DESCRIPTION:

描述:

The gethostuuid() function returns a 16-byte uuid_t specified by id, that uniquely identifies the current machine. Be aware that the hardware identifiers that gethostuuid() uses to generate the UUID can themselves be modified.

函数的作用是:返回一个由id指定的16字节的uuid_t,它唯一标识当前机器。请注意,gethostuuid()用于生成UUID的硬件标识符本身可以被修改。

The wait argument is a pointer to a struct timespec that specifies the maximum time to wait for the result. Setting the tv_sec and tv_nsec fields to zero means to wait indefinitely until it completes.

等待参数是一个指向struct timespec的指针,它指定等待结果的最长时间。将tv_sec和tv_nsec字段设置为零意味着无限期地等待直到完成。

RETURN VALUES:

返回值:

The gethostuuid() function returns zero on success or -1 on error.

gethostuuid()函数在成功或-1错误上返回零。

ERRORS

错误

The gethostuuid() functions fails if:

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.

#4


7  

This would be easier to answer if you told us what language you were using. The information is obtainable without any shell commands through the SystemConfiguration framework, and also through IOKit if you want to get your hands really dirty.

如果你告诉我们你用的是什么语言,这就更容易回答了。通过SystemConfiguration框架,无需任何shell命令即可获得该信息,而且如果您想让您的手非常脏的话,也可以通过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];
}

#5


5  

/*
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;
}

#6


1  

Running:

运行:

system_profiler | grep 'Serial Number (system)'

in a terminal returns what it likely a unique id. That works on my 10.5 box, I'm not sure what the correct string will be in other versions of OS X.

在一个终端返回它可能是唯一的id。这在我的10.5框上工作,我不确定正确的字符串将在其他版本的OS X。

#7


1  

As some people above have hinted, you can use a Terminal command to get a hardware ID.

正如上面的一些人所暗示的,您可以使用一个终端命令来获得一个硬件ID。

I assume you want to do this in code however so I would take a look at the NSTask class in Cocoa. It basically lets you run terminal commands inside your application.

我假设你想在代码中做这个,所以我要看一下Cocoa的NSTask类。它基本上让您在应用程序中运行终端命令。

This code is an example of how to use NSTask in Cocoa. It sets up the environment to execute the "killall" command. It passes it the arguement "Finder".

这段代码是如何在Cocoa中使用NSTask的示例。它设置了执行“killall”命令的环境。它通过了争论者“发现者”。

It's the equivilent of running "killall Finder" on the command line, which will kill the Finder obviously.

它是在命令行上运行“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];

#8


0  

System Profiler (in Applications - Utilities) contains most of this kind of info. It has your serial number and your mac address (no relation to Mac. All computers have a mac address which is pretty much unique to every network card).

系统分析器(在应用程序中)包含大多数此类信息。它有你的序列号和你的mac地址(和mac没有关系。所有的电脑都有一个mac地址,这在每个网卡上都是独一无二的)。

#1


14  

Try this Terminal command:

试试这个终端命令:

ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s\n", line[4]); }'

From here

从这里

Here is that command wrapped in Cocoa (which could probably be made a bit cleaner):

下面是用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];

#2


31  

For C/C++:

对于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);    
}

#3


7  

Why not try gethostuuid()? Here's the documentation from the Mac OS X System Calls Manual:

为什么不试试gethostuuid()?以下是Mac OS X系统调用手册的文档:

NAME:

名称:

 gethostuuid -- return a unique identifier for the current machine

SYNOPSIS:

剧情简介:

 #include <unistd.h>

 int gethostuuid(uuid_t id, const struct timespec *wait);

DESCRIPTION:

描述:

The gethostuuid() function returns a 16-byte uuid_t specified by id, that uniquely identifies the current machine. Be aware that the hardware identifiers that gethostuuid() uses to generate the UUID can themselves be modified.

函数的作用是:返回一个由id指定的16字节的uuid_t,它唯一标识当前机器。请注意,gethostuuid()用于生成UUID的硬件标识符本身可以被修改。

The wait argument is a pointer to a struct timespec that specifies the maximum time to wait for the result. Setting the tv_sec and tv_nsec fields to zero means to wait indefinitely until it completes.

等待参数是一个指向struct timespec的指针,它指定等待结果的最长时间。将tv_sec和tv_nsec字段设置为零意味着无限期地等待直到完成。

RETURN VALUES:

返回值:

The gethostuuid() function returns zero on success or -1 on error.

gethostuuid()函数在成功或-1错误上返回零。

ERRORS

错误

The gethostuuid() functions fails if:

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.

#4


7  

This would be easier to answer if you told us what language you were using. The information is obtainable without any shell commands through the SystemConfiguration framework, and also through IOKit if you want to get your hands really dirty.

如果你告诉我们你用的是什么语言,这就更容易回答了。通过SystemConfiguration框架,无需任何shell命令即可获得该信息,而且如果您想让您的手非常脏的话,也可以通过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];
}

#5


5  

/*
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;
}

#6


1  

Running:

运行:

system_profiler | grep 'Serial Number (system)'

in a terminal returns what it likely a unique id. That works on my 10.5 box, I'm not sure what the correct string will be in other versions of OS X.

在一个终端返回它可能是唯一的id。这在我的10.5框上工作,我不确定正确的字符串将在其他版本的OS X。

#7


1  

As some people above have hinted, you can use a Terminal command to get a hardware ID.

正如上面的一些人所暗示的,您可以使用一个终端命令来获得一个硬件ID。

I assume you want to do this in code however so I would take a look at the NSTask class in Cocoa. It basically lets you run terminal commands inside your application.

我假设你想在代码中做这个,所以我要看一下Cocoa的NSTask类。它基本上让您在应用程序中运行终端命令。

This code is an example of how to use NSTask in Cocoa. It sets up the environment to execute the "killall" command. It passes it the arguement "Finder".

这段代码是如何在Cocoa中使用NSTask的示例。它设置了执行“killall”命令的环境。它通过了争论者“发现者”。

It's the equivilent of running "killall Finder" on the command line, which will kill the Finder obviously.

它是在命令行上运行“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];

#8


0  

System Profiler (in Applications - Utilities) contains most of this kind of info. It has your serial number and your mac address (no relation to Mac. All computers have a mac address which is pretty much unique to every network card).

系统分析器(在应用程序中)包含大多数此类信息。它有你的序列号和你的mac地址(和mac没有关系。所有的电脑都有一个mac地址,这在每个网卡上都是独一无二的)。