C#中的交互式控制台I/O包装器/拦截器-问题是什么?
周末,我试图在C#中组装一个交互式控制台拦截器/包装器,方法是重新混合我在SO和其他网站上找到的一些代码示例 就我目前的情况而言,我无法从控制台可靠地读取数据。有什么快速指示吗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() {
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。