Help us understand the problem. What is going on with this article?

[C#] コンソールアプリの標準入出力を奪ってゴニョゴニョする

やりたいこと

既存のコンソールアプリケーションについて、その標準入出力を非同期で制御してゴニョゴニョしてみる!

ただし、完全なる自由は手に入らない。
深く制御したい場合は、ソースを直接いじってフレームワーク化などをする必要がある。

要は、「コンソールアプリの機能を自前のアプリケーションに使いたい、でもソースコードいじる程でもない」って時にやること!

環境

Windows10、Visual Studio 2017

すること

例えばFormsアプリケーションにおいて、XXX.exeの標準出力を監視しつつ標準入力してみる
ちなみに、実際に作ったツールは https://github.com/sensuikan1973/Edax_AutoLearning_Tool です

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Sample_Asynchronous
{
    public partial class Form1 : Form
    {
        // 同ディレクトリにあるXXX.exeのパスを取得
        string XXX_Path = Path.GetDirectoryName(Application.ExecutablePath) + "XXX.exe";

        // イベントハンドラ
        public delegate void MyEventHandler(object sender, DataReceivedEventArgs e);
        public event MyEventHandler myEvent = null;

        // 外部プロセス(XXX.exe)を宣言
        Process xxx_process = null;

         /**
         * @brief コンストラクタ
         *        XXX.exeを起動する
         */
        public Form1()
        {
            //イベントハンドラを作成
            myEvent = new MyEventHandler(event_DataReceived);

            xxx_process = new Process();
            // パス指定
            xxx_process.StartInfo.FileName = XXX_Path;

            // 非同期処理のために、ShellExecuteを使わない設定にする
            // BeginOutputReadLine()を利用するための条件
            xxx_process.StartInfo.UseShellExecute        = false;

            // 非同期読込での完了イベントとなるイベントハンドラを設定
            // BeginOutputReadLine()を利用するための条件
            xxx_process.OutputDataReceived += new DataReceivedEventHandler(process_DataReceived);

            // 標準入出力をリダイレクト
            xxx_process.StartInfo.RedirectStandardOutput = true;
            xxx_process.StartInfo.RedirectStandardInput  = true;

            // XXX.exeのコンソールは邪魔なので開かない
            xxx_process.StartInfo.CreateNoWindow         = true; 

            // ついにプロセス起動!
            xxx_process.Start();

            // 標準出力の非同期読込を開始
            xxx_process.BeginOutputReadLine();
        }

        /**
         * @brief 非同期で出力を読み込む
         *        メインスレッドにアクセスする場合は、Invokeメソッドを利用し、スレッドの同期をとる必要がある
         */
        void process_DataReceived(object sender, DataReceivedEventArgs e)
        {
            this.Invoke(myEvent, new object[2] { sender, e });
        }

        /**
         * @brief XXX.exeの標準出力を見て、その内容に応じて処理をしてみる     
         */
        void event_DataReceived(object sender, DataReceivedEventArgs e)
        {
          // --------------------
          // e.Dataの中身を見て、色々処理できる!
          // --------------------

         // 例えば、"星"という文字が出力に含まれていたら、"Starだね"という文字を標準入力してみる
          if (e.Data.Contains("星"))
          {
              xxx_process.StandardInput.WriteLine("Starだね");
          }
        }

        /**
         * @brief Formロード時
         */
        private void Form1_Load(object sender, EventArgs e)
        {
            // Formが閉じられた時のイベントを登録
            this.FormClosed  += new FormClosedEventHandler(Form1_Closed);
        }

        /**
         * @brief Formが閉じられた時の処理
         *        外部プロセス(xxx.exe)をkillする
         */
        private void Form1_Closed(object sender, FormClosedEventArgs e)
        {
            Properties.Settings.Default.Save();
            try
            {
                if (xxx_process != null)
                {
                    xxx_process.Kill();
                    xxx_process.Close();
                    xxx_process.Dispose();
                }
            }
            catch (InvalidOperationException exc) { }
        }

    }
}
sensuikan1973
Flutter+GCP/Firebase. Othello player.
https://github.com/sensuikan1973
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした