已设置Console流,未处理异常仍输出到控制台?原因及解决方法
未捕获异常未写入自定义Console流的原因及解决方法
问题原因
Console.SetOut和Console.SetError仅负责重定向Console类主动触发的输出/错误写入操作(如Console.WriteLine、Console.Error.WriteLine)。而未处理的异常由.NET运行时的默认异常处理机制直接处理,该机制会绕过Console类,将异常信息写入操作系统原生的标准错误流(stderr),而非你配置的自定义TextWriter,因此异常信息会直接显示在控制台窗口。
解决方法
方法1:捕获全局未处理异常事件
注册AppDomain.CurrentDomain.UnhandledException事件,拦截所有未处理的异常,手动将信息写入自定义错误流:
using System; using System.IO; using System.Text; class Program { static void Main(string[] args) { // 使用using确保流资源自动释放 using var outputStream = new StreamWriter( new FileStream("C:/Users/User/Desktop/Testing/RedirectOut.txt", FileMode.Truncate), Encoding.UTF8, 2); using var errorStream = new StreamWriter( new FileStream("C:/Users/User/Desktop/Testing/RedirectError.txt", FileMode.Truncate), Encoding.UTF8, 2); Console.SetOut(outputStream); Console.SetError(errorStream); // 注册全局未处理异常事件 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // 测试代码 int y = 5; Console.WriteLine(y / 0); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { if (e.ExceptionObject is Exception ex) { Console.Error.WriteLine($"未处理异常信息:"); Console.Error.WriteLine($"消息: {ex.Message}"); Console.Error.WriteLine($"调用栈:\n{ex.StackTrace}"); // 强制刷新流,确保内容写入文件 Console.Error.Flush(); } } }
方法2:用try-catch包裹整个入口逻辑
如果控制台应用逻辑集中在Main方法,直接用try-catch包裹所有代码,捕获所有异常并写入自定义流:
using System; using System.IO; using System.Text; class Program { static void Main(string[] args) { using var outputStream = new StreamWriter( new FileStream("C:/Users/User/Desktop/Testing/RedirectOut.txt", FileMode.Truncate), Encoding.UTF8, 2); using var errorStream = new StreamWriter( new FileStream("C:/Users/User/Desktop/Testing/RedirectError.txt", FileMode.Truncate), Encoding.UTF8, 2); Console.SetOut(outputStream); Console.SetError(errorStream); try { // 测试代码 int y = 5; Console.WriteLine(y / 0); } catch (Exception ex) { Console.Error.WriteLine($"未处理异常信息:"); Console.Error.WriteLine($"消息: {ex.Message}"); Console.Error.WriteLine($"调用栈:\n{ex.StackTrace}"); Console.Error.Flush(); // 以错误码退出程序 Environment.Exit(1); } } }
方法3:处理异步未捕获异常
如果应用包含异步代码,还需要注册TaskScheduler.UnobservedTaskException事件,捕获异步任务中未被观察到的异常:
// 在Main方法开头添加事件注册 TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { // 标记异常已处理,避免程序终止(可选) e.SetObserved(); foreach (var ex in e.Exception.InnerExceptions) { Console.Error.WriteLine($"异步未处理异常信息:"); Console.Error.WriteLine($"消息: {ex.Message}"); Console.Error.WriteLine($"调用栈:\n{ex.StackTrace}"); } Console.Error.Flush(); }
内容的提问来源于stack exchange,提问作者Jason9789
相关产品推荐
相关产品推荐

