3

SO や他のサイトで見つけたいくつかのコード サンプルをリミックスして、週末に C# でインタラクティブなコンソール インターセプター/ラッパーをまとめようとしていました。

私が今持っているものでは、コンソールから確実に読み返すことができません。簡単な指針はありますか?

public class ConsoleInterceptor
{
    Process _interProc;

    public event Action<string> OutputReceivedEvent;

    public ConsoleInterceptor()
    {
        _interProc = new Process();
        _interProc.StartInfo = new ProcessStartInfo("cmd");
        InitializeInterpreter();
    }

    public ConsoleInterceptor(string command)
    {
        _interProc = new Process();
        _interProc.StartInfo = new ProcessStartInfo(command);
        InitializeInterpreter();
    }

    public Process InterProc
    {
        get
        {
            return _interProc;
        }
    }

    private void InitializeInterpreter()
    {
        InterProc.StartInfo.RedirectStandardInput = true;
        InterProc.StartInfo.RedirectStandardOutput = true;
        InterProc.StartInfo.RedirectStandardError = true;
        InterProc.StartInfo.CreateNoWindow = true;
        InterProc.StartInfo.UseShellExecute = false;
        InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        bool started = InterProc.Start();

        Redirect(InterProc.StandardOutput);
        Redirect(InterProc.StandardError);

    }

    private void Redirect(StreamReader input)
    {
        new Thread((a) =>
        {
            var buffer = new char[1];
            while (true)
            {
                if (input.Read(buffer, 0, 1) > 0)
                    OutputReceived(new string(buffer));
            };
        }).Start();
    }

    private void OutputReceived(string text)
    {
        if (OutputReceivedEvent != null)
            OutputReceivedEvent(text);
    }


    public void Input(string input)
    {
        InterProc.StandardInput.WriteLine(input);
        InterProc.StandardInput.Flush();
    }
}

私は何を達成しようとしていますか?これは小さなユースケースです。2 つのテキスト ボックスがあるとします。

//Create my interceptor
 ConsoleInterceptor interc = new ConsoleInterceptor("cmd");
//Show the output in a textbox
     interc.OutputReceivedEvent += (data) =>
                {
                    this.Invoke(new Action<string>((s)=> this.textBoxOut.Text += s) ,data);
                };



 //Capture user input and pass that to the above interceptor
  private void textInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                interc.Input(textInput.Text);
            }
        }
4

2 に答える 2

1

出力ストリームをループする別のスレッドを使用する代わりに、ハンドラをProcess.OutputDataReceived Eventにアタッチできます。これは、BeginOutputReadLine を呼び出した後、プロセスがリダイレクトされた StandardOutput ストリームに行を書き込むときに発生しますすでに行われています)。

リンクに完全な例があり、うまくいけば役立つはずです。

于 2010-05-24T16:54:48.000 に答える
0

任意のコンソール プロセスと完全に互換性を持たせるには、3 つの個別のスレッドが必要です。これらはメインスレッドに追加されます。サンプル コードには、必要な 3 つのスレッドのうちの 1 つ (stdout) しかありません。

于 2010-05-24T18:01:10.213 に答える