J'essaie d'exécuter une commande externe à partir du code java, mais il y a une différence que j'ai remarquée entre Runtime.getRuntime().exec(...)
et new ProcessBuilder(...).start()
.
Lors de l'utilisation Runtime
:
Process p = Runtime.getRuntime().exec(installation_path +
uninstall_path +
uninstall_command +
uninstall_arguments);
p.waitFor();
exitValue est 0 et la commande se termine ok.
Cependant, avec ProcessBuilder
:
Process p = (new ProcessBuilder(installation_path +
uninstall_path +
uninstall_command,
uninstall_arguments)).start();
p.waitFor();
la valeur de sortie est 1001 et la commande se termine au milieu, bien qu'elle waitFor
retourne.
Que dois-je faire pour résoudre le problème ProcessBuilder
?
cmd.exe
.Regardez comment
Runtime.getRuntime().exec()
passe la commande String auProcessBuilder
. Il utilise un tokenizer et décompose la commande en tokens individuels, puis invoqueexec(String[] cmdarray, ......)
lequel construit unProcessBuilder
.Si vous construisez le
ProcessBuilder
avec un tableau de chaînes au lieu d'une seule, vous obtiendrez le même résultat.Le
ProcessBuilder
constructeur prend unString...
vararg, donc passer la commande entière comme une seule chaîne a le même effet que l'appel de cette commande entre guillemets dans un terminal:la source
Il n'y a aucune différence entre
ProcessBuilder.start()
etRuntime.exec()
parce que la mise en œuvre deRuntime.exec()
est:Donc code:
devrait être le même que:
Merci dave_thompson_085 pour le commentaire
la source
public Process exec(String command, String[] envp, File dir)
-String
NONString[]
- qui appelleStringTokenizer
et met les jetons dans un tableau qui est ensuite passé (indirectement) àProcessBuilder
, ce qui est une différence comme correctement indiqué par les trois réponses d'il y a 7 ans.Oui, il y a une différence.
La
Runtime.exec(String)
méthode prend une seule chaîne de commande qu'elle divise en une commande et une séquence d'arguments.Le
ProcessBuilder
constructeur prend un tableau (varargs) de chaînes. La première chaîne est le nom de la commande et les autres sont les arguments. (Il existe un constructeur alternatif qui prend une liste de chaînes, mais aucun ne prend une seule chaîne composée de la commande et des arguments.)Donc, ce que vous dites à ProcessBuilder de faire est d'exécuter une "commande" dont le nom contient des espaces et d'autres fichiers indésirables. Bien sûr, le système d'exploitation ne trouve pas de commande portant ce nom et l'exécution de la commande échoue.
la source
Runtime.exec(cmd)
est en fait un raccourci pourRuntime.exec(cmd.split("\\s+"))
. LaProcessBuilder
classe n'a pas de constructeur qui est un équivalent direct deRuntime.exec(cmd)
. C'est ce que je veux dire dans ma réponse.new ProcessBuilder("command arg1 arg2")
l'start()
appel ne fera pas ce que vous attendez. Il échouera probablement et ne réussira que si vous avez une commande avec des espaces dans son nom. C'est précisément le problème que se pose le PO!