Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Aleco

macrumors regular
Original poster
Aug 7, 2009
152
129
I've written a class to run a command checking if the OS is Windows or Mac.

Code:
if (currentOS.contains("WINDOWS")) {
                        args = new String[] { "cmd.exe",  "/c",  "dir", "|",  "find", "/i",  "Serial Number is" };
            } else if (currentOS.contains("MAC")) {
						args = new String[] { "system_profiler", "SPHardwareDataType", "|", "grep", "Hardware UUID" };
            } else {
						args = new String[] { "" };
			}

When it's been run on a Windows Machine, it works perfectly! When I run it on my Mac, it just returns a simple text saying, "Disabled."

Is this because Mac has some restrictions to access some data through exec?

Just to let you know I'm setting args, so then I use the following to run it:
Code:
Runtime.getRuntime().exec(args);

If you need the full source, it's HERE.

Thanks!
 
Are you making sure you're doing a case-insensitive comparison by converting the OS string to UPPERCASE first? Also, have you tested what the OS string actually is on a Mac (by, say, printing it) before attempting to parse it? That'll get the OS detection working properly. As for your other question... it looks like your syntax is okay, but it looks like you're passing too many arguments. Try combining everything on the Mac side into one command string, like this:
Code:
args = new String[] { "system_profiler SPHardwareDataType | grep Hardware UUID" };
 
Checking the OS works just fine, using your suggestion gives me this error:

Code:
java.io.IOException: Cannot run program "system_profiler SPHardwareDataType | grep Hardware UUID": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more
 
Checking the OS works just fine, using your suggestion gives me this error:

Code:
java.io.IOException: Cannot run program "system_profiler SPHardwareDataType | grep Hardware UUID": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more
I know what's causing that. You have to use the full path to system_profiler for it to work properly.

Code:
args = new String[] { "/usr/sbin/system_profiler SPHardwareDataType | grep Hardware UUID" };
 
Code:
if (currentOS.contains("WINDOWS")) {
                        args = new String[] { "cmd.exe",  "/c",  "dir", "|",  "find", "/i",  "Serial Number is" };
            } else if (currentOS.contains("MAC")) {
						args = new String[] { "system_profiler", "SPHardwareDataType", "|", "grep", "Hardware UUID" };
            } else {
						args = new String[] { "" };
			}

When it's been run on a Windows Machine, it works perfectly! When I run it on my Mac, it just returns a simple text saying, "Disabled."

Is this because Mac has some restrictions to access some data through exec?

No, it's because Runtime.exec() is not a shell. A shell is the command-line interpreter that parses things like quoted strings and pipe symbols.

Your Windows command-line is essentially running a shell: cmd.exe, the Windows command-line interpreter.

To get the equivalent on a Mac (or other Unix-like platform), your command-line must exec a shell, and the command-line args must be the interpretable command-line.

In bash, your command-line at Terminal.app would be:

system_profiler SPHardwareDataType | grep "Hardware UUID"

The bash invocation that treats remaining args as interpretable command-line is:

bash -c ..interpreted..

So the command-line should be:

bash -c 'system_profiler SPHardwareDataType | grep "Hardware UUID"'

You should be able to translate that into a suitable array of exec() Strings by the propert parsing. I leave this as an exercise. Note: the resulting String[] should contain exactly 3 Strings; if you can't get the answer, ask again and I'll post specific code that's been tested.


And wrldwzrd89's answer is flawed for two reasons:

1. Runtime.exec() is not a shell. Not even when the arg is a single String. It is not parsed the same as the C function system(). Read the docs for exec(String) and then read how a default StringTokenizer parses tokens.

2. Even if it were a shell, the grep pattern is unquoted.
 
Thanks for your replies.

@wrldwzrd89:
I tried you're method, however I'm given an error:
Code:
java.io.IOException: Cannot run program "/usr/sbin/system_profiler SPHardwareDataType | grep Hardware UUID": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more

@chown33:
Thanks for you're reply, this is actually somewhat logical however I'm not getting the 3 string array part. :s It's somehow eating me up, because of the single quotes between the double quotes are the grep pattern. Would you mind helping me out? :(
 
Thanks for your replies.

@wrldwzrd89:
I tried you're method, however I'm given an error:
Code:
java.io.IOException: Cannot run program "/usr/sbin/system_profiler SPHardwareDataType | grep Hardware UUID": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more

@chown33:
Thanks for you're reply, this is actually somewhat logical however I'm not getting the 3 string array part. :s It's somehow eating me up, because of the single quotes between the double quotes are the grep pattern. Would you mind helping me out? :(
You need to escape the quote characters with backslashes - like this: \"text\"
 
I used the following:
Code:
"bash -c", "system_profiler SPHardwareDataType | grep ", "\"Hardware UUID\""

Received this error:
Code:
java.io.IOException: Cannot run program "bash -c": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more
 
I used the following:
Code:
"bash -c", "system_profiler SPHardwareDataType | grep ", "\"Hardware UUID\""

Received this error:
Code:
java.io.IOException: Cannot run program "bash -c": error=2, No such file or directory	at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)	at java.lang.Runtime.exec(Runtime.java:593)	at java.lang.Runtime.exec(Runtime.java:466)	at getSerial.run(getSerial.java:25)	at getSerial.main(getSerial.java:12)Caused by: java.io.IOException: error=2, No such file or directory	at java.lang.UNIXProcess.forkAndExec(Native Method)	at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)	at java.lang.ProcessImpl.start(ProcessImpl.java:91)	at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)	... 4 more

Good try.

Each arg must be in its own String. The command-line must be a single String. Putting those together:

"bash",
"-c",
"system_profiler SPHardwareDataType | grep \"Hardware UUID\""
 
I used the following:
Code:
"bash -c", "system_profiler SPHardwareDataType | grep ", "\"Hardware UUID\""

Hmm, I just checked using Leopard 10.5.6, and I don't see anything in the output from the system_profiler SPHardwareDataType command that contains the word "UUID", so I hope you're prepared to get an empty response.

I do see "Serial Number", so maybe you'll want to use that instead.

This is on a Core 2 Duo Mac mini (about a year old).

YMMV.
 
I originally was going to use the Serial Number, but I just changed it to Hardware UUID, just for testing purposes.

On my MBP, it does give me a Hardware UUID.

Originally the case for this program is to get ones Hard Drive Serial Number.

Edit:
Seems like the Hardware UUID was added after the 10.5.8 update
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.