DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DOSコマンドを実行し出力データを取得する

ProcessStartInfo.RedirectStandardOutputプロパティをTrueとし、プロセスの出力をProcessインスタンスのStandardOutputプロパティ(StreamReaderクラス)に書き込むようにし、ここから書き込まれたデータを取得します。

ヘルプによると、下の例の様にWaitForExitをReadToEndの後にしないと、親プロセスと子プロセスの両方でブロック処理が発生し、デッドロックの原因となるということなので、注意が必要です。また、標準出力と標準エラー出力の両方をリダイレクトし、両方を読み取ろうとすると同じ問題が起こるとのことです。この解決には、それぞれの処理のために2つのスレッドを作成する方法が推奨されています。

下の例ではDOSのDIRコマンドを実行して、その出力結果を取得しています。

VB.NET
コードを隠すコードを選択
Dim results As String
Dim psi As New System.Diagnostics.ProcessStartInfo()

'ComSpecのパスを取得する
psi.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
'出力を読み取れるようにする
psi.RedirectStandardInput = False
psi.RedirectStandardOutput = True
psi.UseShellExecute = False
'ウィンドウを表示しないようにする
psi.CreateNoWindow = True
'コマンドラインを指定("/c"は実行後閉じるために必要)
psi.Arguments = "/c dir c:\ /w"
'起動
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
'出力を読み取る
results = p.StandardOutput.ReadToEnd
'出力された結果を表示
Console.WriteLine(results)
'WaitForExitはReadToEndの後である必要がある
'(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit()
C#
コードを隠すコードを選択
System.Diagnostics.ProcessStartInfo psi =
    new System.Diagnostics.ProcessStartInfo();

//ComSpecのパスを取得する
psi.FileName = System.Environment.GetEnvironmentVariable("ComSpec");

//出力を読み取れるようにする
psi.RedirectStandardInput = false;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
//ウィンドウを表示しないようにする
psi.CreateNoWindow = true;
//コマンドラインを指定("/c"は実行後閉じるために必要)
psi.Arguments = @"/c dir c:\ /w";
//起動
System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
//出力を読み取る
string results = p.StandardOutput.ReadToEnd();
//WaitForExitはReadToEndの後である必要がある
//(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit();

//出力された結果を表示
Console.WriteLine(results);

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。