105

Runtime.getRuntime().exec(...)Java コードから外部コマンドを実行しようとしていますが、との間には違いがあることに気付きました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ですか?

4

4 に答える 4

109

のさまざまなオーバーロードはRuntime.getRuntime().exec(...)、文字列の配列または単一の文字列のいずれかを取ります。の単一文字列オーバーロードは、文字列配列を取得するオーバーロードのexec()1つに文字列配列を渡す前に、文字列を引数の配列にトークン化しますexec()。一方ProcessBuilder、コンストラクターは、文字列のvarargs配列または文字列のaのみを取りListます。ここで、配列またはリスト内の各文字列は、個別の引数であると見なされます。いずれにせよ、取得された引数は、実行するためにOSに渡される文字列に結合されます。

したがって、たとえば、Windowsでは、

Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2");

DoStuff.exe指定された2つの引数を使用してプログラムを実行します。この場合、コマンドラインはトークン化されて元に戻されます。でも、

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2");

DoStuff.exe -arg1 -arg2名前がにあるプログラムがたまたまない限り、失敗しC:\ます。これは、トークン化がないためです。実行するコマンドは、すでにトークン化されていると見なされます。代わりに、

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2");

または代わりに

List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
于 2011-07-28T09:18:29.810 に答える
20

Runtime.getRuntime().exec()String コマンドを に渡す方法を見てくださいProcessBuilder。トークナイザーを使用し、コマンドを個々のトークンに分解してからexec(String[] cmdarray, ......)ProcessBuilder.

ProcessBuilder単一の文字列ではなく文字列の配列でを構築すると、同じ結果が得られます。

ProcessBuilderコンストラクターはvarargString...を受け取るため、コマンド全体を単一の文字列として渡すと、ターミナルでそのコマンドを引用符で囲んで呼び出すのと同じ効果があります。

shell$ "command with args"
于 2011-07-28T08:34:00.430 に答える
17

はい、違いがあります。

  • このRuntime.exec(String)メソッドは、コマンドと一連の引数に分割する単一のコマンド文字列を受け取ります。

  • ProcessBuilderコンストラクターは、文字列の(varargs) 配列を取ります。最初の文字列はコマンド名で、残りは引数です。(文字列のリストを取る別のコンストラクターがありますが、コマンドと引数からなる単一の文字列を取るものはありません。)

したがって、ProcessBuilder に指示しているのは、名前にスペースやその他のジャンクが含まれる「コマンド」を実行することです。もちろん、オペレーティング システムはその名前のコマンドを見つけることができず、コマンドの実行は失敗します。

于 2011-07-28T08:34:20.710 に答える