I'm trying to execute an external command from java code, but there's a difference I've noticed between Runtime.getRuntime().exec(...)
and new ProcessBuilder(...).start()
.
When using Runtime
:
Process p = Runtime.getRuntime().exec(installation_path + uninstall_path + uninstall_command + uninstall_arguments); p.waitFor();
the exitValue is 0 and the command is terminated ok.
However, with ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path + uninstall_path + uninstall_command, uninstall_arguments)).start(); p.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
?
exec(String[] cmdarray, String[] envp) method executes the specified command and arguments in a separate process with the specified environment. This is a convenience method. An invocation of the form exec(cmdarray, envp) behaves in exactly the same way as the invocation exec(cmdarray, envp, null).
Constructs a process builder with the specified operating system program and arguments. This is a convenience constructor that sets the process builder's command to a string list containing the same strings as the command array, in the same order.
Runtime features a static method called getRuntime() , which retrieves the current Java Runtime Environment. That is the only way to obtain a reference to the Runtime object. With that reference, you can run external programs by invoking the Runtime class's exec() method.
ProcessBuilder is not thread safe, as stated in the javadoc.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With