Java アプリ (Win7 64 ビットの Eclipse Helios 内でデバッグ モードで実行されている Tomcat サーバーの一部) 内から wkhtmltopdf を起動しています。
String cmd[] = {"wkhtmltopdf", htmlPathIn, pdfPathOut};
Process proc = Runtime.getRuntime().exec( cmd, null );
proc.waitFor();
しかし、waitFor()
決して戻りません。Windows タスク マネージャーでプロセスを確認できます (exec() に渡したコマンド ラインでは問題ないようです)。そしてそれは動作します。wkhtmltopdf は、期待どおりの場所に、期待どおりの PDF を生成します。プロセスがまだ実行中であっても(手動で終了する前に)、開いたり、名前を変更したりできます。
コマンドラインからは、すべて問題ありません。
c:\wrk>wkhtmltopdf C:\Temp\foo.html c:\wrk\foo.pdf ページを読み込んでいます (1/6) ページを数える (2/6) リンクの解決 (4/6) ヘッダーとフッターの読み込み (5/6) ページの印刷 (6/6) 終わり
プロセスは問題なく終了し、人生は続きます。
ではruntime.exec()
、wkhtmltopdf が終了しない原因は何でしょうか?
proc.getInputStream() を取得して "Done" を探すこともできますが、それは... 卑劣です。もっと一般的なものが欲しい。
作業ディレクトリの有無にかかわらず exec() を呼び出しました。空の「env」配列の有無にかかわらず試しました。喜びはありません。
プロセスがハングするのはなぜですか? 修正するにはどうすればよいですか?
PS: 他のいくつかのコマンド ライン アプリでこれを試しましたが、どちらも同じ動作を示します。
さらなる重役の悩み。
標準出力とエラーを読み込もうとしていますが、成功しません。コマンド ラインから、私のコマンド ライン エクスペリエンスと非常によく似たものがあるはずですが、proc.getInputStream() によって返された入力ストリームを読み取ると、すぐに EOL (-1、私は を使用していますinputStream.read()
) を取得します。
Process の JavaDoc を確認したところ、これが見つかりました
親プロセスは、これらのストリームを使用して、サブプロセスに入力をフィードし、サブプロセスから出力を取得します。一部のネイティブ プラットフォームでは、標準の入力ストリームと出力ストリームに対して限られたバッファ サイズしか提供されないため、サブプロセスの入力ストリームの書き込みまたは出力ストリームの読み取りが迅速に行われないと、[b]サブプロセスがブロックされ、さらにはデッドロック[/b]が発生する可能性があります。
強調が追加されました。だから私はそれを試しました。プロセスを強制終了するまで、標準出力 inputStream の最初の「read()」がブロックされました...
WKHTMLTOPDF を使用
一般的なコマンドライン ap & no params を使用すると、「使用状況をダンプして終了」する必要があり、適切な std::out を吸い出してから終了します。
面白い!
JVMのバージョンの問題? 1.6.0_23 を使用しています。最新は... v24です。変更ログを確認したところ、有望なものは何もありませんが、とにかく更新してみます。
わかった。入力ストリームがいっぱいにならないようにしてください。そうしないとブロックされます。小切手。 .close()
これを防ぐこともできますが、それほど明るくはありません。
それは一般的に機能します(私がテストした一般的なコマンドラインアプリを含む)。
ただし具体的には落ちる。wkhtmltopdf は、ASCII グラフィック プログレス バーを実行するために端末操作/カーソルを使用しているようです。これにより、正しい値が返されるのではなく、inputStream がすぐに EOF を返すようになっていると思います。
何か案は?契約を破ることはほとんどありませんが、それは間違いなくナイス・オブ・ハヴです.