Estoy tratando de ejecutar un comando externo desde el código Java, pero he notado una diferencia entre Runtime.getRuntime().exec(...)
y new ProcessBuilder(...).start()
.
Al usar Runtime
:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
exitValue es 0 y el comando finaliza correctamente.
Sin embargo, con ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
el valor de salida es 1001 y el comando termina en el medio, aunque waitFor
regresa.
¿Qué debo hacer para solucionar el problema ProcessBuilder
?
fuente
cmd.exe
.Mira cómo
Runtime.getRuntime().exec()
pasa el comando String alProcessBuilder
. Utiliza un tokenizador y descompone el comando en tokens individuales, luego invocaexec(String[] cmdarray, ......)
cuál construye unProcessBuilder
.Si construye el
ProcessBuilder
con una matriz de cadenas en lugar de una sola, obtendrá el mismo resultado.El
ProcessBuilder
constructor toma unString...
vararg, por lo que pasar el comando completo como una sola cadena tiene el mismo efecto que invocar ese comando entre comillas en una terminal:fuente
No hay diferencia entre
ProcessBuilder.start()
yRuntime.exec()
porque la implementación deRuntime.exec()
es:Entonces codifique:
debe ser el mismo que:
Gracias dave_thompson_085 por comentar
fuente
public Process exec(String command, String[] envp, File dir)
-String
NOString[]
- que llamaStringTokenizer
y coloca los tokens en una matriz que luego se pasa (indirectamente) aProcessBuilder
, lo que ES una diferencia como se indica correctamente en las tres respuestas de hace 7 años.Sí, hay una diferencia.
El
Runtime.exec(String)
método toma una sola cadena de comando que divide en un comando y una secuencia de argumentos.El
ProcessBuilder
constructor toma una matriz (varargs) de cadenas. La primera cadena es el nombre del comando y el resto son los argumentos. (Hay un constructor alternativo que toma una lista de cadenas, pero ninguno que toma una sola cadena que consta del comando y los argumentos).Entonces, lo que le está diciendo a ProcessBuilder que haga es ejecutar un "comando" cuyo nombre tiene espacios y otra basura en él. Por supuesto, el sistema operativo no puede encontrar un comando con ese nombre y la ejecución del comando falla.
fuente
Runtime.exec(cmd)
es efectivamente un atajo paraRuntime.exec(cmd.split("\\s+"))
. LaProcessBuilder
clase no tiene un constructor que sea un equivalente directo deRuntime.exec(cmd)
. Este es el punto que estoy expresando en mi respuesta.new ProcessBuilder("command arg1 arg2")
lastart()
llamada no hará lo que espera. Probablemente fallará y solo tendrá éxito si tiene un comando con espacios en su nombre. ¡Este es precisamente el problema por el que se pregunta el OP!