コード内で別プロセスを起動する際には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を投げるのもありです。まあお好みで。