提问人:sdbbs 提问时间:9/9/2023 更新时间:9/9/2023 访问量:21
异步 C# StartInfo 进程仅当 stderr 未重定向时才会转储 stdout 行?
Asynchronous C# StartInfo process dumps stdout lines, only if stderr is not redirected?
问:
我正在开发一个运行进程的 C# 应用程序,并且输出行根据 c# 运行 CL exe 或批量 cpture 输出 LIVE 到 textbox? 实时(异步)输出,代码如下:
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();
现在,问题是,似乎可能会用 stderr 和 stdout 重定向做一些奇怪的事情......所以我观察到的是:tool_exe
- 如果 RedirectStandardError 不为 true(行注释) - 那么在运行时,我得到:
System.InvalidOperationException: StandardError has not been redirected.
at System.Diagnostics.Process.BeginErrorReadLine()
...但除此之外,代码运行良好,文本框实时更新,进程成功退出。
- 但是,如果我尝试通过取消注释该行并设置new_process来纠正该异常。StartInfo.RedirectStandardError = true - 然后,当程序运行时,只打印一行(_cmd_OutputDataReceived只触发一次),然后 C# 程序似乎冻结,进程似乎没有退出(所以我必须从 Windows 任务管理器关闭所有内容)?!
我无法想象为什么会发生这种行为(为什么它只有在我遇到异常时才有效)?!
我唯一注意到的是,上面的代码在点击处理程序的上下文中运行;当使用 RedirectStandardError = true 运行构建时,当它冻结时,我实际上在输出中看到了一些我原本期望的消息,显示在 VS2019 的调试输出窗口中(可能在调试对象关闭之后)?
有谁知道这里发生了什么,我怎样才能无一例外地进行正常操作?
答:
0赞
sdbbs
9/9/2023
#1
似乎通过以这种方式重新组织代码,我可以无一例外地在 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();
评论
OutputDataReceived
Process
RedirectStandardError = true;
new_process.BeginErrorReadLine();
new_process
WaitForExit()
BeginErrorReadLine()
RedirectStandardError
WaitForExit()
new_process
MyAppendTextBox1
new_process