Reputation: 15906
I have a program that takes the Console output and writes it to a logfile, however it no longer shows up in the console window. Is there a way to keep it in the window but write it to the log file as well?
Update:
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 is a constant set in the class. It basically tells it whether it is using the console window or not (readline is not called, etc, if not in console).
So is there a way to write to both the console and the file?
Upvotes: 3
Views: 4871
Reputation: 81
Finally i leave the class like this:
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));
}
}
Upvotes: 0
Reputation: 16257
When you call Console.SetOut, you specify where Console should write to. If you don't (i.e. the way Console is typically used), and you call Console.Write, it checks if it has an output writer, and if not, sets it with
stream = OpenStandardOutput(256);
and then
Encoding encoding = Encoding.GetEncoding((int) Win32Native.GetConsoleOutputCP());
writer = TextWriter.Synchronized(new StreamWriter(stream, encoding, 256, false) { HaveWrittenPreamble = true, AutoFlush = true });
So you should be able to do what you're doing now, and if you also want to echo everything to standard out as if you hadn't redirected Console, you can create your own writer using a stream you open yourself using Console.OpenStandardOutput
method. The Win32Native
used in that code is internal, so you don't have access to it, but you can use the Console.OutputEncoding
to retrieve the encoding that it's using.
Something you can also try is using the Console.Out
property to get and hang onto the standard output TextWriter just before you call SetOut. Then you can just use that to echo to standard output.
Upvotes: 0
Reputation: 47975
You could simply read that stream log it and print it out.
It depends a little on your code if you assign the output stream to the inputstream of the outfile this could be a little harder if you read the content to a buffer that should be a little easier.
About your update I would suggest that you exchange all Console
with a custom logging function e.g. a instance of MyLogger (code below) . Which writes your output to the console and to your log file.
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);
}
}
Upvotes: 3
Reputation: 4340
I think you can do something like this:
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));
}
}
You will have to "register" the wrapper with calling ConsoleDecorator.SetToConsole(); After that, every Console.WriteLine call will get to the custom method and there you can fire an event and get the text written in other places (logging for example).
if you will want to use that way, you will have to make the class a singleton and then you can have access to the even registration from other classes (which supposed to write to log file when the even is fired)
Upvotes: 2