【C#】Processで起動したアプリの標準出力をリダイレクトする・改良版

投稿者: | 2011年9月27日

前回、Processで起動した別exeの標準出力をリダイレクトするアプリを作成した。
前回は標準出力を読み取るためにProcess#StandardOutput.ReadLine()メソッドを使った。
このメソッドは、標準出力があるまで現在の処理を止めてしまうため、別スレッドで実行させる必要があった。
そのため、やや複雑なプログラムを書いていた。
C#2.0から追加されたProcess#BeginOutputReadLine()メソッドを使うと、非同期に標準出力を読み取ることが出来る。
前回のプログラムを、このメソッドを使うように改良してみた。
以下に、そのプログラムを示す。

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        private Process process = null;

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// OnClosing処理
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosing(CancelEventArgs e)
        {
            // スレッド・プロセス終了
            if (process != null)
            {
                if (!process.HasExited)
                {
                    process.CancelOutputRead();
                    process.Kill();
                    process.WaitForExit();
                }

                process = null;
            }

            base.OnClosing(e);
        }

        /// <summary>
        /// ボタン押下時の処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if( process == null )
            {
                process = new Process();

                ProcessStartInfo startInfo = new ProcessStartInfo("Win32ConsoleApplication");
                startInfo.CreateNoWindow = true;
                startInfo.RedirectStandardOutput = true;
                startInfo.UseShellExecute = false;

                process.StartInfo = startInfo;
                process.Start();

                // リダイレクトがあったときに呼ばれるイベントハンドラ
                process.OutputDataReceived += 
                new DataReceivedEventHandler(delegate(object obj, DataReceivedEventArgs args)
                {
                    // UI操作のため、表スレッドにて実行
                    this.BeginInvoke(new Action<String>(delegate(String str)
                    {
                        if (!this.Disposing && !this.IsDisposed)
                        {
                            this.textBox1.AppendText(str);
                            this.textBox1.AppendText(Environment.NewLine);
                        }
                    }), new object[] { args.Data });
                });

                // 非同期ストリーム読み取りの開始
                // (C#2.0から追加されたメソッド)
                process.BeginOutputReadLine();
            }
        }
    }
}

実行結果は前回と変わらない。

自分でスレッドを立てる処理を書かなくて良くなった分、プログラムが多少すっきりした。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です