.NET 6控制台程序跨进程调用时Console.Error.WriteLine失效问题
问题分析与解决
问题现象
有两个基于.NET 6.0开发的控制台应用程序:
- 直接运行目标程序时,以下代码执行正常:
string l_ErrMsg = "Error !"; Console.Error.WriteLine(l_ErrMsg); // 正常输出 Console.WriteLine(l_ErrMsg); // 正常输出
- 当通过另一个控制台程序调用该目标程序时,
Console.Error.WriteLine(l_ErrMsg)无法输出内容,但Console.WriteLine(l_ErrMsg)仍正常工作:
string l_ErrMsg = "Error !"; Console.Error.WriteLine(l_ErrMsg); // 无输出 Console.WriteLine(l_ErrMsg); // 正常输出
调用方的代码如下:
using (var process = new System.Diagnostics.Process()) { process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.WorkingDirectory = "\\Some\\Path"; process.StartInfo.FileName = "MyApp.exe"; string l_errorOut = null; process.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => { l_errorOut += e.Data; }); string l_CmdLine = string.Format("--Arg1={0}", argument1); process.StartInfo.Arguments = l_CmdLine; lbProcessStarted = process.Start(); }
问题原因
你已经开启了标准错误流的重定向(RedirectStandardError = true),也注册了ErrorDataReceived事件,但没有启动异步读取标准错误流的操作,导致目标程序输出到标准错误的内容无法被捕获,看起来像是"无法正常工作"。同时当前代码未等待进程执行完成,也可能导致输出内容丢失。
解决方法
修改调用方代码,补充关键步骤:
- 启动异步读取标准错误流:调用
process.BeginErrorReadLine() - (可选)若需要捕获标准输出,同样注册
OutputDataReceived事件并调用process.BeginOutputReadLine() - 等待进程执行完成:调用
process.WaitForExit(),确保所有输出都被完整捕获
修改后的完整代码示例:
using (var process = new System.Diagnostics.Process()) { process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.WorkingDirectory = "\\Some\\Path"; process.StartInfo.FileName = "MyApp.exe"; string l_errorOut = string.Empty; string l_stdOut = string.Empty; // 注册标准错误接收事件,过滤空内容避免无效拼接 process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { l_errorOut += e.Data + Environment.NewLine; } }; // 注册标准输出接收事件(按需添加) process.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { l_stdOut += e.Data + Environment.NewLine; } }; string l_CmdLine = string.Format("--Arg1={0}", argument1); process.StartInfo.Arguments = l_CmdLine; bool lbProcessStarted = process.Start(); // 启动异步读取流 process.BeginErrorReadLine(); process.BeginOutputReadLine(); // 等待进程执行完毕 process.WaitForExit(); // 读取完成后即可使用捕获到的输出内容 Console.WriteLine("标准输出内容:"); Console.WriteLine(l_stdOut); Console.WriteLine("标准错误内容:"); Console.WriteLine(l_errorOut); }
额外说明
- 若目标程序为同步输出模式,也可使用同步读取方式,注意需先读取标准输出再读取标准错误(或反之),避免死锁:
process.Start(); string stdOut = process.StandardOutput.ReadToEnd(); string stdErr = process.StandardError.ReadToEnd(); process.WaitForExit();
- 后台线程触发的事件中,建议使用
StringBuilder进行字符串拼接,比直接+=更高效且线程安全。
内容的提问来源于stack exchange,提问作者Imran Khan
相关产品推荐
相关产品推荐

