我正在开发一个 C# 应用程序,其中运行一个进程,并且输出行按照 c# run CL exe 或批处理 cpture 输出实时输出到文本框? 实时(异步)输出,代码如下这个:
Process new_process = new Process();
new_process.StartInfo.FileName = tool_exe;
new_process.StartInfo.Arguments = tool_arguments;
new_process.StartInfo.RedirectStandardInput = true;
new_process.StartInfo.RedirectStandardOutput = true;
//new_process.StartInfo.RedirectStandardError = true;
new_process.StartInfo.UseShellExecute = false;
new_process.StartInfo.CreateNoWindow = true;
string line;
void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
line = e.Data;
MyAppendTextBox1(line);
}
void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
MyAppendTextBox1("err: " + e.Data);
}
bool did_start = new_process.Start();
if (did_start)
{
new_process.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
new_process.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
//new_process.Exited += new EventHandler(_cmd_Exited);
new_process.BeginOutputReadLine();
new_process.BeginErrorReadLine();
}
new_process.WaitForExit();
现在,问题是,似乎
tool_exe
本身可能会通过 stderr 和 stdout 重定向做一些奇怪的事情......所以我观察到的是:
System.InvalidOperationException: StandardError has not been redirected.
at System.Diagnostics.Process.BeginErrorReadLine()
...但除此之外,代码运行良好,文本框实时更新,进程成功退出。
我根本无法想象为什么会发生这种行为(为什么只有当我遇到异常时它才起作用)?!
我唯一注意到的是上面的代码在点击处理程序的上下文中运行;当使用 RedirectStandardError = true 运行构建时,当它冻结时,我实际上看到了一些我原本期望在输出中出现的消息,这些消息显示在 VS2019 的调试输出窗口中(可能在调试对象关闭之后)?
有人知道这里发生了什么吗?我怎样才能无一例外地正常运行?
似乎通过这种方式重新组织代码,我可以让它在 stdout 和 stderr 正确重定向的情况下运行,没有异常(但通过以下更改,WaitForExit() 不再起作用:
Process new_process = new Process();
new_process.StartInfo.FileName = tool_exe;
new_process.StartInfo.Arguments = tool_arguments;
new_process.EnableRaisingEvents = true; // https://stackoverflow.com/q/4504170
new_process.StartInfo.RedirectStandardInput = true;
new_process.StartInfo.RedirectStandardOutput = true;
new_process.StartInfo.RedirectStandardError = true;
new_process.StartInfo.UseShellExecute = false;
new_process.StartInfo.CreateNoWindow = true;
string line;
void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
line = e.Data;
MyAppendTextBox1(line);
}
void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
MyAppendTextBox1("err: " + e.Data);
}
void _cmd_Exited(object sender, EventArgs e)
{
new_process.OutputDataReceived -= new DataReceivedEventHandler(_cmd_OutputDataReceived);
new_process.ErrorDataReceived -= new DataReceivedEventHandler(_cmd_ErrorDataReceived);
new_process.Exited -= new EventHandler(_cmd_Exited);
}
new_process.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
new_process.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
new_process.Exited += new EventHandler(_cmd_Exited);
new_process.Start();
new_process.BeginOutputReadLine();
new_process.BeginErrorReadLine();