I have a simple console application, and I have used Console.WriteLine
in many places to display to the user the activities being performed. But, at the end I want to save all the Console output to a log file also. Currently, I have something like this:
if (!Directory.Exists(LOG_DIRECTORY)) {
Directory.CreateDirectory(LOG_DIRECTORY);
}
long ticks = DateTime.Now.Ticks;
string logFilename = ticks.ToString() + ".txt";
string filePath = Directory.GetCurrentDirectory() + "\\" + LOG_DIRECTORY + "\\" + logFilename;
FileStream ostream = null;
StreamWriter writer = null;
TextWriter oldOut = Console.Out;
try
{
ostream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
writer = new StreamWriter(ostream);
}
catch (Exception ex)
{
Console.WriteLine("Cannot open {0} for writing.", logFilename);
Console.WriteLine(ex.Message);
return;
}
Console.SetOut(writer);
Console.WriteLine("{0}", Directory.GetCurrentDirectory());
Console.SetOut(oldOut);
writer.Close();
ostream.Close();
Console.WriteLine("\n\nDone!");
The point is that this will print the stuff directly into the file and nothing is printed in the Console. Is there any way to workaround this? Please note that I need the Console.WriteLine
output to be directly in real time to be written to the console, whereas, for writing to a log file, it can be done at the end of the program, where nearly everything else is finished.
You can either create your own component to write to multiple outputs or you can use a logging tool such as NLog. This can be configured such that in the <targets>
section you have something like;
<target name="debugger" xsi:type="Debugger" layout="${level}>${message} (${exception:format=ToString})"/>
<target name="console" xsi:type="ColoredConsole" layout="${date:format=dd-MM-yyyy HH\:mm\:ss} - ${message}" />
<target name="FullCSVFile" xsi:type="File" fileName="${specialfolder:folder=LocalApplicationData}\YourApp\YourApp-${date:format=yyyy-MM-dd}.csv">
<layout xsi:type="CsvLayout">
<column name="Index" layout="${counter}" />
<column name="ThreadID" layout="${threadid}" />
<column name="Time" layout="${longdate}" />
<column name="Severity" layout="${level:uppercase=true}" />
<column name="Location" layout="${callsite:className=False:fileName=True:includeSourcePath=False:methodName=False}" />
<column name="Detail" layout="${message}" />
<column name="Exception" layout="${exception:format=ToString}" />
</layout>
</target>
Then in the rules
section, you'd have;
<logger name="*" minlevel="Debug" writeTo="console" />
<logger name="*" minlevel="Debug" writeTo="debugger" />
<logger name="*" minlevel="Debug" writeTo="FullCSVFile" />
To actually do the write operation, you'd have something like the following in your C# code;
// at a class level;
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
// later in code that writes to both targets...
_logger.Info("Something happened!");
What about saving console output in variable like string array
or List<string>
? Then do the File.WriteAllText(filepath, consoleOutputArray);
I mean this way:
class Program
{
static void Main(string[] args)
{
List<string> textStorage = new List<string>();
string exampleData = "Ford Mustang";
Console.WriteLine(exampleData);
SaveOutput(ref textStorage, exampleData);
System.IO.File.WriteAllLines(@"C://Desktop//MyFolder", textStorage);
}
public static void SaveOutput(ref List<string> textStorage, string output)
{
textStorage.Add(output);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With