【C#】起動したプロセスの標準出力をプログラムで取得する

目次

概要

外部アプリケーションやコマンド(Git, Python, コマンドプロンプト等)を実行し、そのコンソール画面に表示される結果(標準出力)をC#の文字列変数として取り込む方法です。 ProcessStartInfoRedirectStandardOutput プロパティを有効にすることで、パイプ経由で出力ストリームを読み取ることが可能になります。

仕様(入出力)

  • 入力
    • 実行するコマンド名と引数
  • 出力
    • コマンドの実行結果テキスト(string
  • 必須設定
    • UseShellExecutefalse に設定する必要があります。
    • RedirectStandardOutputtrue に設定する必要があります。

基本の使い方

Process オブジェクトの設定を行い、開始後に StandardOutput.ReadToEnd() で出力を全て読み込みます。

var psi = new ProcessStartInfo
{
    FileName = "git",
    Arguments = "--version",
    UseShellExecute = false,        // シェル機能を使わない(必須)
    RedirectStandardOutput = true,  // 出力をリダイレクトする(必須)
    CreateNoWindow = true           // 黒画面を出さない
};

using (var p = Process.Start(psi))
{
    // 出力を最後まで読み取る
    string result = p.StandardOutput.ReadToEnd();
    p.WaitForExit();
    
    Console.WriteLine(result);
}

コード全文

Gitコマンド(git config --list)を実行して設定一覧を取得し、最初の数行を表示するコンソールアプリケーションです。

using System;
using System.Diagnostics;
using System.Text;
using System.Linq;

class Program
{
    static void Main()
    {
        // 1. プロセス起動情報の構築
        var psi = new ProcessStartInfo();
        psi.FileName = "git";               // 実行するコマンド
        psi.Arguments = "config --list";    // 引数
        
        // 【重要】標準出力を取得するための必須設定
        psi.UseShellExecute = false;        
        psi.RedirectStandardOutput = true;
        
        // 文字化けを防ぐためのエンコーディング指定
        // (Git for Windowsは通常UTF-8を出力します)
        psi.StandardOutputEncoding = Encoding.UTF8;

        try
        {
            Console.WriteLine("--- Git設定の取得を開始 ---");

            // 2. プロセスの起動
            using (var p = Process.Start(psi))
            {
                if (p == null) return;

                // 3. 標準出力の読み取り
                // ReadToEnd() はプロセスがストリームを閉じるまで待機して読み込む
                // 注意: 大量の出力がある場合は非同期読み取り推奨
                string output = p.StandardOutput.ReadToEnd();

                // プロセスの終了待機
                p.WaitForExit();

                // 4. 結果の加工と表示
                // 改行コードで分割して配列化
                string[] lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                Console.WriteLine($"取得した行数: {lines.Length}行");
                Console.WriteLine("--- 先頭8行を表示 ---");

                // LINQで先頭8行を取得して表示
                foreach (var line in lines.Take(8))
                {
                    Console.WriteLine(line);
                }
            }
        }
        catch (System.ComponentModel.Win32Exception)
        {
            Console.WriteLine("エラー: Gitコマンドが見つかりませんでした。インストールされているか確認してください。");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"エラー: {ex.Message}");
        }
    }
}

実行結果例

--- Git設定の取得を開始 ---
取得した行数: 25行
--- 先頭8行を表示 ---
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html

カスタムポイント

  • 文字コードの指定
    • psi.StandardOutputEncoding を設定しないと、OSのデフォルト(Shift_JISなど)が使われ、日本語を含む出力が文字化けする可能性があります。対象コマンドに合わせて Encoding.UTF8Encoding.GetEncoding("Shift_JIS") を指定してください。
  • 標準エラー出力の取得
    • エラーメッセージも取得したい場合は、RedirectStandardError = true を設定し、p.StandardError.ReadToEnd() で読み取ります。

注意点

  1. デッドロックの危険性
    • 標準出力と標準エラー出力の両方を同期的に(ReadToEndで)読み取ろうとすると、バッファが一杯になりプロセスが停止するデッドロックが発生する可能性があります。両方を読む場合は、片方を非同期(BeginOutputReadLine)にするなどの対策が必要です。
  2. UseShellExecuteの制約
    • RedirectStandardOutput = true にする場合、UseShellExecute は必ず false にする必要があります。これにより、ファイルの関連付け実行(例: .txt を指定してメモ帳を開く)はできなくなり、実行ファイルのパスを直接指定する必要があります。

応用

非同期イベントによるリアルタイム読み取り

処理時間が長いコマンドの出力を、終了を待たずに1行ずつリアルタイムに取得して表示する方法です。

var psi = new ProcessStartInfo("ping", "127.0.0.1 -n 5")
{
    UseShellExecute = false,
    RedirectStandardOutput = true
};

using (var p = new Process { StartInfo = psi })
{
    // データ受信時のイベントハンドラ
    p.OutputDataReceived += (sender, e) =>
    {
        if (e.Data != null)
        {
            Console.WriteLine($"受信: {e.Data}");
        }
    };

    p.Start();
    p.BeginOutputReadLine(); // 非同期読み取り開始
    p.WaitForExit();
}

まとめ

StandardOutput プロパティを利用することで、コマンドラインツールの実行結果をアプリケーション内に取り込み、ログ解析やデータの連携を行うことが可能になります。実装の際は、必ず UseShellExecute を無効に設定すること、そして文字化けを防ぐために適切なエンコーディングを指定することを忘れないでください。大量の出力を扱う場合やエラー出力も同時に取得する場合は、デッドロックを回避するために非同期読み取りパターンの採用を推奨します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次