using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using System.Globalization;
namespace HelperClasses
{
///
/// Enumerated type used to decide how exceptions will be logged
///
public enum ExceptionLogType
{
/// Exception will be logged to a text file
TextFile,
/// Exception will be logged to the application event log
EventLog,
/// Exception will be logged via email
Email
}
///
/// Class to log unhandled exceptions to a text file, event log or email
///
public class ExceptionLogger
{
///
/// Creates a new instance of the ExceptionLogger class
///
public ExceptionLogger()
{
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(OnThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
}
private string GetExceptionStack(Exception e)
{
StringBuilder message = new StringBuilder();
message.Append(e.Message);
while (e.InnerException != null)
{
e = e.InnerException;
message.Append(Environment.NewLine);
message.Append(e.Message);
}
return message.ToString();
}
delegate void LogExceptionDelegate(Exception e);
private void HandleException(Exception e)
{
switch (logType)
{
case ExceptionLogType.Email:
if (MessageBox.Show("An unexpected error occurred - " + e.Message +
". Do you want to submit an error report?", "Error", MessageBoxButtons.YesNo) == DialogResult.No)
return;
break;
case ExceptionLogType.EventLog:
MessageBox.Show("An unexpected error occurred - " + e.Message +
". It will be logged to the event log", "Error");
break;
case ExceptionLogType.TextFile:
MessageBox.Show("An unexpected error occurred - " + e.Message +
". It will be logged to the text file 'BugReport.txt'", "Error");
break;
default:
Debug.Assert(false, "Unrecognised log type - " + logType.ToString());
break;
}
LogExceptionDelegate logDelegate = new LogExceptionDelegate(LogException);
logDelegate.BeginInvoke(e, new AsyncCallback(LogCallBack), null);
}
// Event handler that will be called when an unhandled
// exception is caught
private void OnThreadException(object sender, ThreadExceptionEventArgs e)
{
// Log the exception to a file
HandleException(e.Exception);
}
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
HandleException((Exception)e.ExceptionObject);
}
private void LogCallBack(IAsyncResult result)
{
LogExceptionDelegate logDelegate = (LogExceptionDelegate)((AsyncResult)result).AsyncDelegate;
logDelegate.EndInvoke(result);
}
private ExceptionLogType logType;
///
/// Specifies what type of logging will occur
///
public ExceptionLogType LogType
{
get { return logType; }
set { logType = value; }
}
///
/// writes exception details to a log file
///
private void LogException(Exception exception)
{
DateTime now = System.DateTime.Now;
StringBuilder error = new StringBuilder();
error.Append("Date: " +
System.DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + Environment.NewLine);
error.Append("Computer name: " +
SystemInformation.ComputerName + Environment.NewLine);
error.Append("User name: " +
SystemInformation.UserName + Environment.NewLine);
error.Append("OS: " +
System.Environment.OSVersion.ToString() + Environment.NewLine);
error.Append("Culture: " +
CultureInfo.CurrentCulture.Name + Environment.NewLine);
error.Append("Resolution: " +
SystemInformation.PrimaryMonitorSize.ToString() + Environment.NewLine);
Process[] systemProcesses = Process.GetProcessesByName("System");
if (System.Environment.OSVersion.Version.Major < 6)
{
if (systemProcesses.Length > 0)
error.Append("System up time: " +
(DateTime.Now - systemProcesses[0].StartTime).ToString() + Environment.NewLine);
}
error.Append("App up time: " +
(DateTime.Now - Process.GetCurrentProcess().StartTime).ToString() + Environment.NewLine);
error.Append("Exception class: " +
exception.GetType().ToString() + Environment.NewLine);
error.Append("Exception message: " +
GetExceptionStack(exception) + Environment.NewLine);
error.Append(Environment.NewLine);
error.Append("Stack Trace:");
error.Append(Environment.NewLine);
error.Append(exception.StackTrace);
error.Append(Environment.NewLine);
error.Append(Environment.NewLine);
error.Append("Loaded Modules:");
error.Append(Environment.NewLine);
Process thisProcess = Process.GetCurrentProcess();
foreach (ProcessModule module in thisProcess.Modules)
{
error.Append(module.FileName + " " + module.FileVersionInfo.FileVersion);
error.Append(Environment.NewLine);
}
error.Append(Environment.NewLine);
error.Append(Environment.NewLine);
error.Append(Environment.NewLine);
switch (logType)
{
case ExceptionLogType.TextFile:
LogToFile(error.ToString());
break;
case ExceptionLogType.EventLog:
LogToEventLog(error.ToString());
break;
case ExceptionLogType.Email:
LogToEmail(error.ToString());
break;
default:
Debug.Assert(false, "Unrecognised logType - " + logType.ToString());
break;
}
}
#region email support
private string emailTo;
///
/// Specifies the email address that the exception information will be sent to
///
public string EmailTo
{
get
{
return emailTo;
}
set
{
emailTo = value;
}
}
private string emailFrom;
///
/// Specifies the email address that the exception information will be sent from
///
public string EmailFrom
{
get
{
return emailFrom;
}
set
{
emailFrom = value;
}
}
private string emailTitle;
///
/// Specifies the email title that the exception information email will display
///
public string EmailTitle
{
get
{
return emailTitle;
}
set
{
emailTitle = value;
}
}
private string emailServer;
///
/// Specifies the email server that the exception information email will be sent via
///
public string EmailServer
{
get
{
return emailServer;
}
set
{
emailServer = value;
}
}
private void LogToEmail(string error)
{
MailMessage message = new MailMessage(emailFrom, emailTo, emailTitle, error);
SmtpClient client = new SmtpClient(emailServer);
// Add credentials if the SMTP server requires them.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
client.Send(message);
}
#endregion
private void LogToEventLog(string error)
{
EventLog log = new EventLog("Application");
log.Source = Assembly.GetExecutingAssembly().ToString();
log.WriteEntry(error, EventLogEntryType.Error);
}
private void LogToFile(string error)
{
string filename = Path.GetDirectoryName(Application.ExecutablePath);
filename += Path.DirectorySeparatorChar + "BugReport.txt";
ArrayList data = new ArrayList();
lock (this)
{
if (File.Exists(filename))
{
using (StreamReader reader = new StreamReader(filename))
{
string line = null;
do
{
line = reader.ReadLine();
data.Add(line);
}
while (line != null);
}
}
// truncate the file if it's too long
int writeStart = 0;
if (data.Count > 500)
writeStart = data.Count - 500;
using (StreamWriter stream = new StreamWriter(filename, false))
{
for (int i = writeStart; i < data.Count; i++)
{
stream.WriteLine(data[i]);
}
stream.Write(error);
}
}
}
}
}