Я пытаюсь выполнить внешнюю команду из java-кода, но заметил разницу между Runtime.getRuntime().exec(...)
и new ProcessBuilder(...).start()
.
При использовании Runtime
:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
значение exitValue равно 0, и команда завершена нормально.
Однако с ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
значение выхода - 1001, и команда завершается в середине, хотя и waitFor
возвращается.
Что мне делать, чтобы исправить проблему ProcessBuilder
?
cmd.exe
.Посмотрите, как
Runtime.getRuntime().exec()
передает команду String объектуProcessBuilder
. Он использует токенизатор и разбивает команду на отдельные токены, а затем вызывает,exec(String[] cmdarray, ......)
который создаетProcessBuilder
.Если вы построите
ProcessBuilder
с массивом строк вместо одной, вы получите тот же результат.ProcessBuilder
Конструктор принимаетString...
vararg, поэтому передавая всю команду в виде одной строки имеет тот же эффект, вызывая эту команду в кавычках в терминале:источник
Нет разницы между
ProcessBuilder.start()
и,Runtime.exec()
потому что реализацияRuntime.exec()
:Итак, код:
должно быть таким же, как:
Спасибо dave_thompson_085 за комментарий
источник
public Process exec(String command, String[] envp, File dir)
-String
НЕString[]
- который вызываетStringTokenizer
и помещает токены в массив, который затем передается (косвенно)ProcessBuilder
, что является разницей, как правильно указано в трех ответах от 7 лет назад.Да, разница есть.
Runtime.exec(String)
Метод занимает одну строку команды , что он расщепляет в команду и последовательности аргументов.ProcessBuilder
Конструктор принимает () с переменным числом аргументов массив строк. Первая строка - это имя команды, а остальные - аргументы. (Существует альтернативный конструктор, который принимает список строк, но ни один из них не принимает одну строку, состоящую из команды и аргументов.)Итак, вы говорите ProcessBuilder выполнить «команду», в имени которой есть пробелы и другой мусор. Конечно, операционная система не может найти команду с таким именем, и выполнение команды не выполняется.
источник
Runtime.exec(cmd)
фактически является ярлыком дляRuntime.exec(cmd.split("\\s+"))
. УProcessBuilder
класса нет конструктора, который был бы прямым эквивалентомRuntime.exec(cmd)
. Об этом я и говорю в своем ответе.new ProcessBuilder("command arg1 arg2")
, тоstart()
вызов не будет делать то , что вы ожидаете. Вероятно, это не удастся и будет успешным только в том случае, если у вас есть команда с пробелами в ее имени. Это как раз та проблема, о которой спрашивает ОП!