Introduction
As part of my ongoing Windows and .NET programming efforts, I frequently find a requirement to provide some sort of logging or auditing functionality.
There are several scenarios where a log file is either required or simply very useful:
- Providing intermediate results or status messages for a long running code fragment.
- Providing results in a form that can be saved to an external text file.
- Saving messages that log both expected and unexpected events during the course of processing.
- Providing an audit trail for an application (when started, stopped, etc.).
The library supplants the use of Console.WriteLine, MessageBox and TextOut functionality found in Windows and .NET programming by providing finer grained control over how messages are built, formatted, displayed and saved.
The logging is packages into three sets of classes:
- MessageLog class provides a visual output window for your messages.
- TextLogFile class provides easy way to format messages written directly to a file.
- WindowsEventLog class encapsulates the logic needed to write to a Windows Event Log.
Visual Log Window for App Messages
MessageLog Code Library routines allow you to output messages from your application to a text window. You can search, format, print and save the messages directly from the output window. You can control whether the window is visible from your application.
public MessageLog _messageLog;
.....
_messageLog = new MessageLog();
_messageLog.Caption = "Application Message Log for TestprogMessageLogs";
_messageLog.ShowDatetime = false;
_messageLog.ShowWindow();
.....
.....
private long GetSum(long minNum, long maxNum, long outputEveryInterval, bool showDateTime)
{
long sum = 0;
try
{
_messageLog.Clear();
_messageLog.ShowDatetime = showDateTime;
_messageLog.WriteLine("Running GetSum routine ...");
_messageLog.ShowWindow();
for (long i = minNum; i <= maxNum; i++)
{
sum += i;
if ((i % outputEveryInterval) == 0 || i == maxNum)
{
_msg.Length = 0;
_msg.Append("Sum calculated to " + i.ToString("#,##0"));
_msg.Append(" = ");
_msg.Append(sum.ToString("#,##0"));
_messageLog.WriteLine(_msg.ToString());
}
}
}
catch (System.Exception ex)
{
_msg.Length = 0;
_msg.Append(AppGlobals.AppMessages.FormatErrorMessage(ex));
_messageLog.WriteLine(_msg.ToString());
}
finally
{
;
}
return sum;
}
.....
Visual Message Log Output Window
Text File Logs
You can write formatted application messages to text log files. Output messages can be formatted to automatically include date/time, type of message (Error, Warning, Information, and Alert), name of the application sending the message and name of the computer from which the message was generated.
There is no visual UI for the text log classes. Your code writes directly to the external file.
.....
private long GetSumToOutputFile(string outputFilename, bool appendMessagesIfFileExists,
bool showMessageType, bool showApplicationName,
bool showMachineName,long minNum, long maxNum,
long outputEveryInterval, bool showDateTime)
{
long sum = 0;
TextLogFile logfile = null;
try
{
logfile = new TextLogFile(outputFilename);
logfile.ShowMessageType = showMessageType;
if(showApplicationName)
{
logfile.ApplicationName = "TestprogMessageLogs";
}
if(showMachineName)
{
logfile.MachineName = Environment.MachineName;
}
if(File.Exists(outputFilename))
{
if(appendMessagesIfFileExists == false)
{
logfile.TruncateFile();
}
}
logfile.ShowDatetime = showDateTime;
for (long i = minNum; i <= maxNum; i++)
{
sum += i;
if ((i % outputEveryInterval) == 0 || i == maxNum)
{
_msg.Length = 0;
_msg.Append("Sum calculated to " + i.ToString("#,##0"));
_msg.Append(" = ");
_msg.Append(sum.ToString("#,##0"));
logfile.WriteLine(_msg.ToString(), TextLogFile.LogMessageType.Information);
}
}
if (showMessageType)
{
logfile.WriteLine("This is a test warning message.", TextLogFile.LogMessageType.Warning);
logfile.WriteLine("This is a test error message.", TextLogFile.LogMessageType.Error);
}
}
catch (System.Exception ex)
{
_msg.Length = 0;
_msg.Append(AppGlobals.AppMessages.FormatErrorMessage(ex));
logfile.WriteLine(_msg.ToString(), TextLogFile.LogMessageType.Error);
}
finally
{
;
}
return sum;
}
Sample text file containing log entries
Windows Event Logs
You can write formatted application messages to any of the Windows built-in Event Logs (Application, System, Security and Setup).
public MessageLog _messageLog;
.....
_messageLog = new MessageLog();
_messageLog.Caption = "Application Message Log for TestprogMessageLogs";
_messageLog.ShowDatetime = false;
_messageLog.ShowWindow();
.....
.....
public void OutputMessagesToWindowsApplicationEventLog(string eventSourceName,
int numInformationMessagesToWrite,
int numWarningMessagesToWrite,
int numErrorMessagesToWrite)
{
WindowsEventLog eventLog = null;
try
{
if (WindowsEventLog.SourceExists(eventSourceName) == false)
{
WindowsEventLog.CreateEventSource(eventSourceName);
if (WindowsEventLog.SourceExists(eventSourceName))
{
_msg.Length = 0;
_msg.Append("Event Source ");
_msg.Append(eventSourceName);
_msg.Append(" create succeeded.");
WriteMessageToLog(_msg.ToString());
}
else
{
_msg.Length = 0;
_msg.Append("Event Source ");
_msg.Append(eventSourceName);
_msg.Append(" create failed.");
WriteMessageToLog(_msg.ToString());
}
}
else
{
_msg.Length = 0;
_msg.Append("Event Source ");
_msg.Append(eventSourceName);
_msg.Append(" exists.");
WriteMessageToLog(_msg.ToString());
}
eventLog = new WindowsEventLog(WindowsEventLog.EventLogName.Application, ".", eventSourceName);
for (int i = 1; i <= numInformationMessagesToWrite; i++)
{
_msg.Length = 0;
_msg.Append("Message ");
_msg.Append(i.ToString());
_msg.Append(" from test program.");
eventLog.WriteEntry(_msg.ToString(), WindowsEventLog.WindowsEventLogEntryType.Information);
}
for (int i = 1; i <= numWarningMessagesToWrite; i++)
{
_msg.Length = 0;
_msg.Append("Warning message ");
_msg.Append(i.ToString());
_msg.Append(" from test program.");
eventLog.WriteEntry(_msg.ToString(), WindowsEventLog.WindowsEventLogEntryType.Warning);
}
for (int i = 1; i <= numErrorMessagesToWrite; i++)
{
_msg.Length = 0;
_msg.Append("Error message ");
_msg.Append(i.ToString());
_msg.Append(" from test program.");
eventLog.WriteEntry(_msg.ToString(), WindowsEventLog.WindowsEventLogEntryType.Error);
}
_msg.Length = 0;
_msg.Append("Number of event log messages written = ");
_msg.Append((numInformationMessagesToWrite + numWarningMessagesToWrite + numErrorMessagesToWrite).ToString("#,##0"));
WriteMessageToLog(_msg.ToString());
}
catch (System.Exception ex)
{
_msg.Length = 0;
_msg.Append(AppGlobals.AppMessages.FormatErrorMessage(ex));
_msg.Append(Environment.NewLine);
_msg.Append("Caller must have elevated security permissions (e.g. use Run As Administrator) to create and delete event sources and event logs.");
WriteMessageToLog(_msg.ToString());
}
finally
{
;
}
}
.....
public void WriteMessageToLog(string msg)
{
if (_messageLog != null)
_messageLog.WriteLine(msg);
}
Application Event Log entries written by above sample code
Points of Interest
The MessageLog class allows you to easily build visual log output windows. This class is especially useful when testing program code but is also very useful for providing a shipping application with an easy to implement status/output window.
There are additional libraries included in the sample code. The additional libraries are used by the test program that demonstrates how to use the various library routines. These additional libraries are part of a general pfCodeLibrary project. Documentation and code samples for these helper classes can be found in the pfCodeLibrary project on CodePlex at https://pfcodelibrary.codeplex.com/.
History
Article was initially published on July 6, 2016 on CodeProject.
Article was republished on July 7, 2016 to fix display of output windows.
A version of this code library was previously published on CodePlex at
https://messageloggingcodelibrary.codeplex.com/