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();
    }
}

我想要完成什么?这是一个小型用例。假设我有两个文本框。

//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

为了与任何控制台进程完全兼容,您需要三个独立的线程:一个写入 stdin,一个从 stdout 读取,一个从 stderr 读取。这些是对您的主线程的补充。您的示例代码只有所需的三个线程之一(stdout)。

于 2010-05-24T18:01:10.213 回答