2009-06-01 20 views
26

Die Mac OS X-Entwicklung ist ein ziemlich neues Tier für mich, und ich bin gerade dabei, einige Software zu portieren. Für Software-Lizenzierung und Registrierung muss ich in der Lage sein, eine Art Hardware-ID zu generieren. Es muss nichts Besonderes sein; Ethernet-MAC-Adresse, Festplatten-Seriell, CPU-Seriell, so etwas.Einzigartige Hardware-ID unter Mac OS X

Ich habe es unter Windows abgedeckt, aber ich habe keine Ahnung von Mac. Jede Idee von dem, was ich tun muss, oder wo ich Informationen dazu bekommen kann, wäre großartig!

Edit:

Für alle anderen, die daran interessiert ist, das ist der Code, den ich mit Qt QProcess Klasse am Ende mit:

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(); 

Hinweis: Ich bin mit C++.

Antwort

14

Versuchen Sie, diese Terminal-Befehl:

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

Von here

Hier ist dieser Befehl in Cocoa gewickelt (was wahrscheinlich ein bisschen sauberer gemacht werden könnte):

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

Danke, das scheint die Art zu sein, die am besten funktioniert. Die Ausgabe des System Profilers scheint auf verschiedenen Systemen unterschiedlich zu sein, so dass ich fürchte, dass eine Flut von Supportanfragen die Software nicht registrieren kann. – Gerald

+0

Diese Technik ist jedoch leicht zu knacken - ersetzen Sie einfach/usr/sbin/ioreg durch ein Skript, das eine bekanntermaßen gute UUID (anstelle einer maschinenspezifischen UUID) zurückgibt. Ein direkter Aufruf in die Systembibliotheken (zum Beispiel @ yairchus Antwort) macht das Cracken ein bisschen weniger trivial. – smokris

+0

@smokris andernfalls entspricht dies IORegistryEntryFromPath? – tofutim

1

Running:

system_profiler | grep 'Serial Number (system)' 

in einem Terminal zurückgibt, was es wahrscheinlich eine eindeutige ID. Das funktioniert auf meiner 10.5-Box, ich bin mir nicht sicher, was die richtige Zeichenfolge in anderen Versionen von OS X sein wird.

+1

Es gibt tatsächlich einige Macs, die ohne eine Seriennummer versendet haben, so sollten Sie nichts tun, was eine eindeutige Seriennummer auf der mit 100% beruht. – smorgan

+1

'system_profiler' wird manchmal auch eine Weile dauern. Wenn Sie eine DVD im DVD-Laufwerk haben, wird sie zum Beispiel hochgefahren. –

+2

Ich habe einige dieser Macs ohne Seriennummer gesehen (und hatte Probleme mit meiner Softwarelizenzierung), aber UUID ist immer da. Sie sollten mit UUID krank sein. – TCB13

0

System Profiler (in Anwendungen - Dienstprogramme) enthält die meisten dieser Art von Informationen. Es hat Ihre Seriennummer und Ihre Mac-Adresse (keine Beziehung zu Mac. Alle Computer haben eine Mac-Adresse, die ziemlich einzigartig für jede Netzwerkkarte ist).

1

Da einige Leute oben angedeutet haben, können Sie einen Terminal-Befehl verwenden, um eine Hardware-ID zu erhalten.

Ich nehme an, Sie möchten dies in Code tun, aber ich würde einen Blick auf die NSTask-Klasse in Cocoa werfen. Im Grunde können Sie Terminal-Befehle in Ihrer Anwendung ausführen.

Dieser Code ist ein Beispiel für die Verwendung von NSTask in Cocoa. Es richtet die Umgebung ein, um den Befehl "killall" auszuführen. Es übergibt es das Argument "Finder".

Es ist das Äquivalent von "killall Finder" auf der Kommandozeile, die den Finder offensichtlich töten wird.

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

Was ist mit der Umwandlung in 'NSString *', und warum 'lastPathComponent' aufrufen? Diese Zeile entspricht "[args addObject: @" Finder "]". – dreamlax

7

Dies wäre einfacher zu beantworten, wenn Sie uns sagten, welche Sprache Sie verwenden. Die Informationen sind ohne Shell-Befehle über das SystemConfiguration-Framework und auch über IOKit verfügbar, wenn Sie Ihre Hände wirklich schmutzig machen wollen.

- (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]; 
} 
+0

Sie haben Recht, ich hätte die Sprache angeben sollen. Ich habe die Frage und die Tags aktualisiert. Ich verwende C++ und das Qt-Framework für die plattformübergreifende Entwicklung. – Gerald

+0

Dann SCNetworkInterfaceGetHardwareAddressString wird es für Sie erhalten, ohne einen anderen Prozess zum Ausführen eines Shell-Skripts zu fälschen. –

+0

macAddress Zuweisung in Zeile 12 erfordert eine Autorelease – Colin

31

Für 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);  
} 
+1

Dies funktionierte für mich mit XCode 5.1 und Mac OS X 10.8.5 –

+1

Dies sollte die angenommene Antwort sein – shawn

+0

kann diese Funktion die gleiche UUID auch Mac-Version in Zukunft aktualisiert zurückgeben? . (nehmen wir an, diese Funktion wird in Zukunft Mac-Version jetzt funktionieren) –

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; 
} 
+1

mit @ Yairchus Code oben gegeben .... :) –

+1

'$ C++ mac_uuid.cpp -framework CoreFoundation -lIOKit' führt zu:' ld: Bibliothek nicht gefunden für - LIOKit Clang: Fehler: Linker-Befehl fehlgeschlagen mit Exit-Code 1 (mit -V, um den Aufruf zu sehen) ' – malat

+0

' g ++ mac_uuid.cpp -o mac_uuid -framework CoreFoundation -framework IOKit' funktioniert für mich –

7

Warum nicht versuchen, gethostuuid()?Hier ist die Dokumentation aus dem Mac OS X Systemhandbuch Anrufe:

Name:

gethostuuid -- return a unique identifier for the current machine 

SYNOPSIS:

#include <unistd.h> 

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

BESCHREIBUNG:

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.

Rückgabewerte:

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

Fehler

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.