gal gal - 4 months ago 108
Java Question

Difference between ProcessBuilder and Runtime.exec()

I'm trying to execute external command from java code, but there's a difference I've noticed.
when running the code:

Process qq=Runtime.getRuntime().exec(
installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments
);
qq.waitFor();


the exitValue is 0 and the command terminated ok.

but when I use:

Process qq=(new ProcessBuilder(
installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments)
).start();
qq.waitFor();


Thanks, but the second code wasn't correct. I use ProcessBuilder this way and it still doesn't work:

Process qq=(new ProcessBuilder(
installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)
).start();
qq.waitFor();


the exit value is 1001 and the command terminates in the middle although waitFor returns.

What should I do to fix the problem with
ProcessBuilder
?

Answer

The various overloads of Runtime.getRuntime().exec(...) take either an array of strings or a single string. The single-string overloads of exec() will tokenise the string into an array of arguments, before passing the string array onto one of the exec() overloads that takes a string array. The ProcessBuilder constructors, on the other hand, only take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument. Either way, the arguments obtained are then joined up into a string that is passed to the OS to execute.

So, for example, on Windows,

Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2");

will run a DoStuff.exe program with the two given arguments. In this case, the command-line gets tokenised and put back together. However,

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2");

will fail, unless there happens to be a program whose name is DoStuff.exe -arg1 -arg2 in C:\. This is because there's no tokenisation: the command to run is assumed to have already been tokenised. Instead, you should use

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2");

or alternatively

List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
Comments