我有一个包含3个控件的表单:
我想要的是让用户在第一个文本框中输入命令,按下按钮以通过第二个文本框输入和接收反馈。
我知道如何使用ProcessStartInfo.RedirectStandardOutput
但是,当我使用StandardOutput.ReadToEnd()
时应用程序会挂起。
我看了一下异步Process.BeginOutputReadLine()
但是,即使我的应用程序没有挂起,但是我在文本框中没有得到任何响应,它什么也没做。
这是我的代码:
public partial class MainForm : Form
{
private void MainForm_Load(object sender, EventArgs e)
{
InitializeInterpreter();
}
private void InitializeInterpreter()
{
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.FileName = "app.exe";
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
InterProc.Start();
}
private static void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
OutputTextBox.Append(Environment.NewLine + outLine.Data);
}
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.Write(CommandtextBox.Text);
InterProc.BeginOutputReadLine();
}
}
有什么办法让我顺利运行吗?感谢。
答案 0 :(得分:6)
如果你想要一些互动的东西,我得到了这个代码(你的修改,下面的修改细节)
private void InitializeInterpreter()
{
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.FileName = "Echoer.exe";
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
bool started = InterProc.Start();
InterProc.BeginOutputReadLine();
}
private void AppendTextInBox(TextBox box, string text)
{
if (this.InvokeRequired)
{
this.Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
}
else
{
box.Text += text;
}
}
private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.WriteLine(CommandTextBox.Text);
}
因此,我将BeginOutputReadLine移动到进程启动后。这确保它实际上只被调用一次。我还做了一个清理线程调用所需的调用。希望这对你有用。
答案 1 :(得分:5)
我找到的最佳解决方案是:
private void Redirect(StreamReader input, TextBox output)
{
new Thread(a =>
{
var buffer = new char[1];
while (input.Read(buffer, 0, 1) > 0)
{
output.Dispatcher.Invoke(new Action(delegate
{
output.Text += new string(buffer);
}));
};
}).Start();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
process = new Process
{
StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
FileName = "app.exe",
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
}
};
if (process.Start())
{
Redirect(process.StandardError, textBox1);
Redirect(process.StandardOutput, textBox1);
}
}
答案 2 :(得分:1)
我使用的代码如下:
public static void Run(string fileName, string arguments, out string standardOutput, out string standardError, out int exitCode)
{
Process fileProcess = new Process();
fileProcess.StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = arguments,
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
};
bool started = fileProcess.Start();
if (started)
{
fileProcess.WaitForExit();
}
else
{
throw new Exception("Couldn't start");
}
standardOutput = fileProcess.StandardOutput.ReadToEnd();
standardError = fileProcess.StandardError.ReadToEnd();
exitCode = fileProcess.ExitCode;
}
但它不是互动的。但如果应用程序是交互式的,那么无论如何都会需要更多的代码。
答案 3 :(得分:0)
你在哪里打StandardOutput.ReadToEnd()
?我曾经遇到过类似的问题,因为我在Process.WaitForExit()
之前打电话给StandardOutput.ReadToEnd()
。我有大量的输入,输出缓冲区在完成之前已满,我的进程被阻止。
您必须在StandardOutput.ReadToEnd()
之前致电Process.WaitForExit()
。