Mac OS X 中的唯一硬件 ID

发布于 2024-07-22 08:04:17 字数 537 浏览 8 评论 0原文

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++。

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.

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!

Edit:

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

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++.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

噩梦成真你也成魔 2024-07-29 08:04:17

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

For 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);    
}
删除会话 2024-07-29 08:04:17

尝试这个终端命令:

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];

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):

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];
彼岸花ソ最美的依靠 2024-07-29 08:04:17

为什么不尝试 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.

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

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.

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.

RETURN VALUES:

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

ERRORS

The gethostuuid() functions fails if:

 [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.
ヅ她的身影、若隐若现 2024-07-29 08:04:17

如果您告诉我们您使用的是什么语言,这个问题会更容易回答。 这些信息无需任何 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];
}

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.

- (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];
}
水波映月 2024-07-29 08:04:17
/*
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;
}
/*
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;
}
单调的奢华 2024-07-29 08:04:17

运行:

system_profiler | grep 'Serial Number (system)'

在终端中返回可能是唯一的 id。 这适用于我的 10.5 机器,我不确定其他版本的 OS X 中正确的字符串是什么。

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.

叫嚣ゝ 2024-07-29 08:04:17

正如上面一些人所暗示的,您可以使用终端命令来获取硬件 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];

As some people above have hinted, you can use a Terminal command to get a hardware 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.

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".

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

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];
不交电费瞎发啥光 2024-07-29 08:04:17

以下命令与 ioreg 命令等效且简单得多。

system_profiler SPHardwareDataType | 系统分析器 awk '/UUID/ { print $3 }

The following is equivalent and far simpler than the ioreg command.

system_profiler SPHardwareDataType | awk '/UUID/ { print $3 }

时光沙漏 2024-07-29 08:04:17

系统分析器(在应用程序 - 实用程序中)包含大部分此类信息。 它有您的序列号和 mac 地址(与 Mac 无关。所有计算机都有一个 mac 地址,对于每个网卡来说几乎都是唯一的)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文