我有一个程序可以获取控制台输出并将其写入日志文件,但它不再显示在控制台窗口中。有没有办法将其保留在窗口中,但也将其写入日志文件?
更新:
appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
TextWriter logtxtWriter = Console.Out;
logstrmWriter = new StreamWriter(appLogStream);
if(!console) Console.SetOut(logstrmWriter);
logstrmWriter.AutoFlush = true;
Console.WriteLine("Started at " + DateTime.Now);
console 是类中设置的常量。它基本上告诉它是否正在使用控制台窗口(如果不在控制台中,则不会调用 readline 等)。
那么有没有办法同时写入控制台和文件?
您可以简单地读取该流并将其记录并打印出来。
如果您将输出流分配给输出文件的输入流,这在一定程度上取决于您的代码,如果您将内容读取到应该更容易的缓冲区,这可能会有点困难。
关于您的更新,我建议您将所有
Console
替换为自定义日志记录功能,例如MyLogger 的实例(代码如下)。它将您的输出写入控制台和日志文件。
class MyLogger {
private FileStream appLogStream;
public MyLogger() {
appLogStream = new FileStream(logFile, FileMode.Append, FileAccess.Write,
FileShare.Read);
appLogStream.WriteLine("Started at " + DateTime.Now);
}
public Write(string msg) {
Console.Write(msg);
appLogStream.Write(msg);
}
public WriteLine(string msg) {
Console.WriteLine(msg);
appLogStream.WriteLine(msg);
}
}
我认为你可以做这样的事情:
public class ConsoleDecorator : TextWriter
{
private TextWriter m_OriginalConsoleStream;
public ConsoleDecorator(TextWriter consoleTextWriter)
{
m_OriginalConsoleStream = consoleTextWriter;
}
public override void WriteLine(string value)
{
m_OriginalConsoleStream.WriteLine(value);
// Fire event here with value
}
public static void SetToConsole()
{
Console.SetOut(new ConsoleDecorator(Console.Out));
}
}
您必须通过调用 ConsoleDecorator.SetToConsole() 来“注册”包装器; 之后,每个 Console.WriteLine 调用都将访问自定义方法,您可以在其中触发事件并获取在其他位置写入的文本(例如日志记录)。
如果您想使用这种方式,则必须使该类成为单例,然后您可以从其他类访问偶数注册(应该在触发偶数时写入日志文件)
当您调用 Console.SetOut 时,您指定 Console 应写入的位置。如果您不这样做(即通常使用 Console 的方式),并且您调用 Console.Write,它会检查它是否有输出编写器,如果没有,则将其设置为
stream = OpenStandardOutput(256);
然后
Encoding encoding = Encoding.GetEncoding((int) Win32Native.GetConsoleOutputCP());
writer = TextWriter.Synchronized(new StreamWriter(stream, encoding, 256, false) { HaveWrittenPreamble = true, AutoFlush = true });
所以你应该能够做你现在正在做的事情,如果你还想将所有内容回显到标准输出,就像你没有重定向控制台一样,你可以使用你自己打开的流来创建你自己的编写器
Console.OpenStandardOutput
方法。该代码中使用的 Win32Native
是内部的,因此您无权访问它,但您可以使用 Console.OutputEncoding
检索它正在使用的编码。
您还可以尝试使用
Console.Out
属性在调用 SetOut 之前获取并挂载到标准输出 TextWriter。然后您可以使用它来回显到标准输出。
最后我就这样离开了课堂:
public class ConsoleDecorator : TextWriter
{
private TextWriter m_OriginalConsoleStream;
public override Encoding Encoding => m_OriginalConsoleStream.Encoding;
public ConsoleDecorator(TextWriter consoleTextWriter)
{
m_OriginalConsoleStream = consoleTextWriter;
}
public override void WriteLine(string value)
{
string cHora = DateTime.Now.ToString("yyyyMMddTHHmm:ss") + "." + DateTime.Now.Millisecond.ToString().PadLeft(3, '0');
string msg = $"{cHora}: {value}";
m_OriginalConsoleStream.WriteLine(msg);
// Fire event here with value
if (Properties.Settings.Default.GenerateLog)
{
// Ruta y nombre del archivo de texto
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "APP_" + DateTime.Now.ToString("yyyyMMdd").Substring(2, 6) + ".Log");
try
{
using (StreamWriter writer = new StreamWriter(filePath, true))
{
writer.Write('\n' + msg);
}
}
catch { }
}
}
public static void SetToConsole()
{
Console.SetOut(new ConsoleDecorator(Console.Out));
}
}