.NET 7控制台应用如何用单语句同时输出至控制台与带时间戳文件?
问题描述
我有一个通过Windows任务计划每日执行的.NET 7控制台应用,调试时控制台输出十分有用,但自动执行时该输出不会被保存。我可以通过任务计划将输出重定向到文件,但更希望将内容同时写入控制台和以时间戳命名的文本文件。
如果单独使用文件文本流写入,就需要重复编写每一条Write/WriteLine语句,这是糟糕的设计。因此我想知道,如何仅用一条Write/WriteLine语句,同时将文本写入控制台和文件?
我曾考虑使用ILogger接口,但该应用仅约70行代码,逻辑简洁,且ILogger的日志级别过滤功能对我而言完全冗余,我只需要记录所有内容,因此ILogger对我的项目来说大材小用。
我不希望重定向控制台输出!我想要将控制台流复制到第二个流中。这类似于命令行中的tee命令,但我要的是不依赖任何命令行参数的代码内实现方法。我在Stack Overflow上找到一个旧解决方案,不过仍希望得到适配.NET 7的方案。
适配.NET 7的实现方案
不需要依赖额外框架或.NET 7新特性,通过自定义TextWriter即可实现控制台输出与文件输出的同步,核心思路是让控制台的输出流同时指向原控制台和文件流。
实现步骤
- 定义一个继承自
TextWriter的类,同时封装原控制台输出流和文件输出流,重写写入方法实现双端输出。 - 生成带时间戳的日志文件名,创建文件流。
- 将
Console.Out和Console.Error替换为自定义的TextWriter,确保所有控制台输出(包括错误信息)都能同步写入文件。
完整代码示例
using System; using System.IO; namespace TeeConsoleExample { class Program { static void Main(string[] args) { // 生成带时间戳的文件名,避免重复 string logFileName = $"app_log_{DateTime.Now:yyyyMMdd_HHmmss}.txt"; using var fileStream = new StreamWriter(logFileName, append: false) { AutoFlush = true }; using var teeWriter = new TeeTextWriter(Console.Out, fileStream); using var teeErrorWriter = new TeeTextWriter(Console.Error, fileStream); // 替换控制台的标准输出和错误输出 Console.SetOut(teeWriter); Console.SetError(teeErrorWriter); // 后续所有Console.WriteLine/Write都会自动同步到控制台和文件 Console.WriteLine("应用启动时间:" + DateTime.Now); Console.WriteLine("执行操作1..."); try { // 模拟错误场景 int num = int.Parse("abc"); } catch (Exception ex) { Console.Error.WriteLine("发生错误:" + ex.Message); } Console.WriteLine("应用执行完成"); } } /// <summary> /// 实现类似tee命令的TextWriter,同时写入两个流 /// </summary> public class TeeTextWriter : TextWriter { private readonly TextWriter _primaryWriter; private readonly TextWriter _secondaryWriter; public override Encoding Encoding => _primaryWriter.Encoding; public TeeTextWriter(TextWriter primary, TextWriter secondary) { _primaryWriter = primary; _secondaryWriter = secondary; } public override void Write(char value) { _primaryWriter.Write(value); _secondaryWriter.Write(value); } public override void Write(string value) { _primaryWriter.Write(value); _secondaryWriter.Write(value); } public override void WriteLine(string value) { _primaryWriter.WriteLine(value); _secondaryWriter.WriteLine(value); } public override void WriteLine() { _primaryWriter.WriteLine(); _secondaryWriter.WriteLine(); } protected override void Dispose(bool disposing) { if (disposing) { _secondaryWriter.Dispose(); } base.Dispose(disposing); } } }
代码说明
TeeTextWriter类:封装了两个TextWriter(原控制台输出和文件流),所有写入操作都会同时转发到这两个流。AutoFlush = true:确保文件流实时写入内容,避免程序意外退出时丢失日志。- 替换
Console.SetOut和Console.SetError:覆盖系统默认的输出流,后续所有控制台输出都会自动触发双端写入,无需修改原有Console.WriteLine代码。 - 使用
using语句:自动释放文件流和自定义Writer资源,避免内存泄漏。
这个方案完全适配.NET 7,且无需引入任何额外依赖,代码轻量符合你的项目规模需求。
内容的提问来源于stack exchange,提问作者Wim ten Brink
相关产品推荐
相关产品推荐

