31
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Process.WaitForExit()でハングしないようにするには

Posted at

コード内で別プロセスを起動する際にはProcessクラスを使いますが、出力をリダイレクトする場合は正しく初期化しないとWaitForExit()がいつまで待っても返って来ません。

リダイレクションのための内部バッファは4Kバイトしかありません。もし呼び出したプロセスが4KB以上出力した場合、その出力が取り出されるまでプロセスが停止するためです。UNIXのパイプの扱いと同じですね。この問題を避ける一番簡単な方法は、簡単なイベントハンドラを用意して適宜データを吸い出してやることです。

以下にpowershellを内部から呼び出すサンプルを書きます。

var command = "powershell.exe";
var arguments = "gci $ENV:TEMP";
var startInfo = new ProcessStartInfo(command, arguments) {
    WorkingDirectory = Environment.CurrentDirectory,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    UseShellExecute = false,
    CreateNoWindow = true
};

var output = new StringBuilder();
var timeout = TimeSpan.FromMinutes(2); // 2分だけ待つ

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

    process.OutputDataReceived += (sender, e) => { if (e.Data != null) { stdout.AppendLine(e.Data); } }; // 標準出力に書き込まれた文字列を取り出す
    process.ErrorDataReceived += (sender, e) => { if (e.Data != null) { stderr.AppendLine(e.Data); } }; // 標準エラー出力に書き込まれた文字列を取り出す
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    var isTimedOut = false;
    
    if (!process.WaitForExit((int)timeout.TotalMilliseconds))
    {
        isTimedOut = true;
        process.Kill();
    }
    process.CancelOutputRead();
    process.CancelErrorRead();

    output.AppendLine(stdout.ToString());
    output.AppendLine(stderr.ToString());
    if (isTimedOut)
        output.AppendLine("TIMEOUT AT " + DateTimeOffset.Now);
}
var resultString = output.ToString();  // これを使う

適当にメソッドにするなりヘルパークラスに入れるなりしてお使いください。タイムアウト発生時、上記サンプルでは文字列に追加していますが、TimeoutExceptionを投げるのもありです。まあお好みで。

31
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?