I am relatively new to C# and would like to see if what I have been using for my exception handling, message and logging is along industry standards. I have created a simple class for the Error Handler and for the logging I use Log4Net. After reading Clean Code, I was thinking about separating DisplayMessage
into 2 different procedures for the message and logging. The log file is usually written to a file server so multiple users can access it; I have enabled MinimalLock
for this purpose. For my example, I have changed the log path to C:\Temp\
. An example of a project I use the Error Handler class and logging in is on GitHub. For reference, I am using Visual Studio 2017 Community.
ErrorHandler.cs
using System;
using System.Windows.Forms;
using log4net;
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
/// <summary>
/// Used to handle exceptions
/// </summary>
public class ErrorHandler
{
private static readonly ILog log = LogManager.GetLogger(typeof(ErrorHandler));
/// <summary>
/// Used to produce an error message and create a log record
/// <example>
/// <code lang="C#">
/// ErrorHandler.DisplayMessage(ex);
/// </code>
/// </example>
/// </summary>
/// <param name="ex">Represents errors that occur during application execution.</param>
/// <remarks></remarks>
public static void DisplayMessage(Exception ex)
{
System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1);
System.Reflection.MethodBase caller = sf.GetMethod();
string currentProcedure = (caller.Name).Trim();
string errorMessageDescription = ex.ToString();
errorMessageDescription = System.Text.RegularExpressions.Regex.Replace(errorMessageDescription, @"\r\n+", " "); //the carriage returns were messing up my log file
string msg = "Contact your system administrator. A record has been created in the log file." + Environment.NewLine;
msg += "Procedure: " + currentProcedure + Environment.NewLine;
msg += "Description: " + ex.ToString() + Environment.NewLine;
log.Error("[PROCEDURE]=|" + currentProcedure + "|[USER NAME]=|" + Environment.UserName + "|[MACHINE NAME]=|" + Environment.MachineName + "|[DESCRIPTION]=|" + errorMessageDescription);
MessageBox.Show(msg, "Unexpected Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Usage Example:
/// <summary>
/// Return the count of items in a delimited list
/// </summary>
/// <param name="valueList">Represents the list of values in a string </param>
/// <param name="delimiter">Represents the list delimiter </param>
/// <returns>the number of values in a delimited string</returns>
public int GetListItemCount(string valueList, string delimiter)
{
try
{
string[] comboList = valueList.Split((delimiter).ToCharArray());
return comboList.GetUpperBound(0) + 1;
}
catch (Exception ex)
{
ErrorHandler.DisplayMessage(ex);
return 0;
}
}
Log4Net
app.config
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline"/>
</layout>
</appender>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="C:\Temp\MyLogFile.log"/>
<appendToFile value="true"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date|%-5level|%message%newline"/>
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="FileAppender"/>
</root>
</log4net>