web-dev-qa-db-ja.com

System.Diagnostics.Processの出力を取得する方法

私はこのようにffmpegを実行します:

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.Start();
p.WaitForExit();

...しかし問題は、ffmpegを備えたコンソールがポップアップしてすぐに消えてしまうため、フィードバックを取得できないことです。プロセスが正しく実行されたかどうかさえわかりません。

だから私はどのようにできますか:

  • 開いたままにするようにコンソールに指示する

  • コンソールが表示したものをC#で取得する

36
marcgg

標準出力ストリームをキャプチャする必要があります。

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
    q += p.StandardOutput.ReadToEnd();
}

StandardErrorでも同様のことを行う必要がある場合があります。その後、qを使用して希望どおりの操作を行うことができます。

私の質問の1つ で発見したように、それは少し気難しいです

Jon Skeetが指摘したように、このような文字列連結を使用することは、賢明なパフォーマンスではありません。代わりに StringBuilder を使用する必要があります。

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
StringBuilder q = new StringBuilder();
while ( ! p.HasExited ) {
    q.Append(p.StandardOutput.ReadToEnd());
}
string r = q.ToString();
53
Lucas Jones

ルーカスの答えには競合状態があります。出力が残っていても、whileループが終了した(または入力されなかった)場合、プロセスがすぐに終了すると、一部のデータが失われる可能性があります。これを防ぐには、別のReadToEndを実行する必要がありますafterプロセスが終了しました。

(私の回答の以前のバージョンと比較して、WaitForExitが必要になったことがprocess.HasExitedフラグはtrueなので、要約すると:)

using (var process = Process.Start(startInfo))
{
    var standardOutput = new StringBuilder();

    // read chunk-wise while process is running.
    while (!process.HasExited)
    {
        standardOutput.Append(process.StandardOutput.ReadToEnd());
    }

    // make sure not to miss out on any remaindings.
    standardOutput.Append(process.StandardOutput.ReadToEnd());

    // ...
}
20
chiccodoro

Ffmpegに直接関連するより具体的な回答については、「-report」コマンドをffmpegに渡すと、プロセスの表示で述べられた内容を含むログが現在のディレクトリにダンプされます。

'-報告する'

コマンドラインとコンソールの完全な出力を、現在のディレクトリのprogram-YYYYMMDD-HHMMSS.logという名前のファイルにダンプします。このファイルはバグレポートに役立ちます。 -loglevel verboseも意味します。

注:環境変数FFREPORTを任意の値に設定しても同じ効果があります。

FFMpeg Documentation から。

4
Ben

この質問が古いことはわかっていますが、とにかく追加します。

コマンドラインプロセスの出力を表示するだけで、コンソールウィンドウからプロセスを起動する場合は、標準入力をリダイレクトするだけで済みます(そうです、間違っているようですが、動作します)。

そう:

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.UseShellExecute = false;
p.RedirectStandardInput = true;
p.Start();
p.WaitForExit();

うまくいくでしょう。

3
Michael Vasquez