«前の日記(2011年02月14日) 最新 次の日記(2011年02月28日)» 編集

日々をアレコレ


2011年02月19日

.NETで別プロセスを起動して非同期でリダイレクトを取る その3

その1その2からの続き。今回が結論のはず。

まず、標準出力の取得にStreamReader.ReadLine()は、今作っているアプリケーションのようにコマンドラインアプリの標準出力のログを表示するような場合には向かないことがわかった。というのも、StreamReader.ReadLine()は現在位置から改行コードまでを読み出すのでラインフィードが表れるまでは完了しないから。例えば、コマンドラインアプリケーションが1行に進捗割合を出力する場合、バックスペースかキャリッジリターンを出力してカーソルを移動させて出力を更新すると、0%から100%までは一切出力を得ることが出来ない。なので、StreamReader.Read()を使って次のように標準出力を取得するのがいいようだ。

private void StartProcess()
{
   proc = new Process();

    // プロセス開始のための情報
    proc.StartInfo.FIleName = "hogehoge.exe";         // 実行ファイル
    proc.StartInfo.UseShellExecute = false;           // シェルは利用しない
    proc.StartInfo.RedirectStandardOutput = ture;     // 出力リダイレクトを有効にする

    // プロセス終了イベントハンドラ登録
    proc.Exited += new EventHandler(procExited);

    output = proc.StandardOutpt;

    // プロセス開始
    proc.Start();

    // リダイレクト監視スレッド
    Thread t = new Thread(new ParameterizedThreadStart,(procGetOutput));
    t.Start(proc.StandardOutput);
}

private void procGetOutput(object param)
{
    StreamReader reader = param as StreamReader;
    try
    {
        while(true)
        {
            char[] buffer = new char[256]; // 読み込みバッファ
            int len = reader.Read(buffer, 0, 256);
            if( len > 0 )
            {
                PutReadLog(buffer, len);   // 読み込みバッファ処理
            }
            else
            {
                Thread.Sleep(10);
            }
        }
    }
    catch(ThreadAbortException)
    {
        // スレッドが中断されたら、ストリームの最後まで読み込む
        while(!reader.EndObStream)
        {
            char[] buffer = new char[256];
            int len = reader.Read(buffer, 0, 256);
            if( len > 0 ) PutReadLog(buffer, len);
        }
    }
}

で、標準出力から得られたchar型配列には、バックスペース、キャリッジリターン、ラインフィード、Null文字も含まれているので、それを受け取る側の処理も一工夫が必要。


«前の日記(2011年02月14日) 最新 次の日記(2011年02月28日)» 編集