C#中的交互式控制台I/O包装器/拦截器-问题是什么?

C#中的交互式控制台I/O包装器/拦截器-问题是什么?,c#,process,console,processstartinfo,C#,Process,Console,Processstartinfo,周末,我试图在C#中组装一个交互式控制台拦截器/包装器,方法是重新混合我在SO和其他网站上找到的一些代码示例 就我目前的情况而言,我无法从控制台可靠地读取数据。有什么快速指示吗 public class ConsoleInterceptor { Process _interProc; public event Action<string> OutputReceivedEvent; public ConsoleInterceptor() {

周末,我试图在C#中组装一个交互式控制台拦截器/包装器,方法是重新混合我在SO和其他网站上找到的一些代码示例

就我目前的情况而言,我无法从控制台可靠地读取数据。有什么快速指示吗

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();
    }
}
公共类控制台接收器
{
进程_interProc;
公共事件行动输出;
公用控制台接收器()
{
_interProc=新流程();
_interProc.StartInfo=新流程StartInfo(“cmd”);
初始化interpreter();
}
公用控制台接收器(字符串命令)
{
_interProc=新流程();
_interProc.StartInfo=新进程StartInfo(命令);
初始化interpreter();
}
公共程序
{
得到
{
返回_interProc;
}
}
私有void初始化interpreter()
{
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 Start=InterProc.Start();
重定向(过程间标准输出);
重定向(过程间标准错误);
}
私有无效重定向(StreamReader输入)
{
新线程((a)=>
{
var buffer=新字符[1];
while(true)
{
if(input.Read(缓冲区,0,1)>0)
OutputReceived(新字符串(缓冲区));
};
}).Start();
}
输出接收的专用void(字符串文本)
{
if(OutputReceivedEvent!=null)
OutputReceivedEvent(文本);
}
公共无效输入(字符串输入)
{
进程间标准输入写入线(输入);
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);
            }
        }
//创建我的拦截器
ConsoleInterceptor interc=新ConsoleInterceptor(“cmd”);
//在文本框中显示输出
interc.OutputReceivedEvent+=(数据)=>
{
this.Invoke(新操作((s)=>this.textBoxOut.Text+=s),数据);
};
//捕获用户输入并将其传递给上述拦截器
私有void textInput_KeyDown(对象发送方,KeyEventArgs e)
{
如果(e.KeyCode==Keys.Enter)
{
交互输入(textInput.Text);
}
}

您可以将处理程序附加到,而不是在输出流上使用另一个线程循环,在调用BeginOutputReadLine后,当进程将一行写入重定向的StandardOutput流(您已经这样做)时,将引发该处理程序


链接中有一个完整的示例,希望能有所帮助。

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

我已经有一次运行cmd或应用程序的示例,然后关闭std输入,并返回结果。关键是,我需要标准输入在整个生命周期中都是开放的-以使其具有交互性。请解释您试图实现的目标。还解释了一个最小用例:)。已经使用BeginOutputReadLine+OutputDataReceived进行了尝试-如果您尝试过,您会发现您也有一个问题。在重定向中,如果您注意到的话,我正在创建两个线程——一个用于阅读stderr,一个用于stdout。