Estou tentando executar um comando externo de código java, mas há uma diferença que notei entre Runtime.getRuntime().exec(...)
e new ProcessBuilder(...).start()
.
Ao usar Runtime
:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
o exitValue é 0 e o comando é encerrado ok.
No entanto, com ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
o valor de saída é 1001 e o comando termina no meio, embora waitFor
retorne.
O que devo fazer para corrigir o problema ProcessBuilder
?
fonte
cmd.exe
.Veja como
Runtime.getRuntime().exec()
passa o comando String para oProcessBuilder
. Ele usa um tokenizer e explode o comando em tokens individuais e, em seguida, invocaexec(String[] cmdarray, ......)
que constrói umProcessBuilder
.Se você construir o
ProcessBuilder
com uma matriz de strings em vez de uma única, obterá o mesmo resultado.O
ProcessBuilder
construtor recebe umString...
vararg, portanto, passar o comando inteiro como uma única String tem o mesmo efeito que invocar esse comando entre aspas em um terminal:fonte
Não há diferença entre
ProcessBuilder.start()
eRuntime.exec()
porque a implementação deRuntime.exec()
é:Então codifique:
deve ser o mesmo que:
Obrigado dave_thompson_085 pelo comentário
fonte
public Process exec(String command, String[] envp, File dir)
-String
NÃOString[]
- que chamaStringTokenizer
e coloca os tokens em uma matriz que é então passada (indiretamente) paraProcessBuilder
, o que É uma diferença conforme declarado corretamente pelas três respostas de 7 anos atrás.Sim, há uma diferença.
O
Runtime.exec(String)
método usa uma única string de comando que é dividida em um comando e uma sequência de argumentos.O
ProcessBuilder
construtor leva um (varargs) array de strings. A primeira string é o nome do comando e o restante são os argumentos. (Há um construtor alternativo que leva uma lista de strings, mas nenhum que leva uma única string consistindo no comando e nos argumentos.)Então, o que você está dizendo ao ProcessBuilder para fazer é executar um "comando" cujo nome contém espaços e outras coisas inúteis. Obviamente, o sistema operacional não consegue encontrar um comando com esse nome e a execução do comando falha.
fonte
Runtime.exec(cmd)
é efetivamente um atalho paraRuntime.exec(cmd.split("\\s+"))
. AProcessBuilder
classe não tem um construtor que seja equivalente direto aRuntime.exec(cmd)
. Este é o ponto que estou defendendo em minha resposta.new ProcessBuilder("command arg1 arg2")
astart()
chamada não fará o que você espera. Provavelmente irá falhar e só terá sucesso se você tiver um comando com espaços no nome. Este é exatamente o problema que o OP está perguntando!