/// <summary> /// Handles logging of messages for events that the application throws out /// </summary> /// <param name="showMessagebox">"True" will force a message box to appear regardless of application settings</param> /// <param name="messageLevel">Integer determining error level based on above legend</param> /// <param name="error">Exception returned from try-catch statement; may be null</param> /// <param name="context">What the application was doing at the time of the message</param> public static void handleMessage(bool showMessagebox, int messageLevel, Exception error, string context) { MessageLevelDefinition messageDef = MessageLevel.level(messageLevel); if (messageLevel <= _eventViewerLoggingLevel) { logEventViewerEvent(messageDef, error, context); } if (messageLevel <= _applicationLogFileLoggingLevel) { logApplicationLogFileEntry(messageDef, error, context); } if (showMessagebox || _debugMode) { if (error != null) { MessageBox.Show(messageDef.messageBoxIntro + "\n\nContext:\n" + context + "\n\nError message:\n" + error.Message, messageDef.messageBoxTitle); } else { MessageBox.Show(messageDef.messageBoxIntro + "\n\nContext:\n" + context + "\n\nNo Exception object generated", messageDef.messageBoxTitle); } } }
/// <summary> /// When given an integer representation of a message level, returns the full MessageDefinition. Returns a default MessageDefinition if none is found. /// </summary> /// <param name="levelNumber">Integer representing message level - matches with the index in the _messageLevelDict</param> /// <returns></returns> public static MessageLevelDefinition level(int levelNumber) { if (_messageLevelDict == null) { buildDefaultDict(); } if (_messageLevelDict.ContainsKey(levelNumber)) { return(_messageLevelDict[levelNumber]); } else { MessageLevelDefinition unconfiguredErrorMessage = new MessageLevelDefinition(); unconfiguredErrorMessage.levelName = "Incorrectly Handled Error"; unconfiguredErrorMessage.messageBoxTitle = "Incorrectly Handled Error"; unconfiguredErrorMessage.messageBoxIntro = "An incorrectly handled error has occurred. Please report this to the developer, who will need to ensure that the error level number has been added to MessageLevel._messageLevelDict."; unconfiguredErrorMessage.windowsErrorLevel = EventLogEntryType.Warning; return(unconfiguredErrorMessage); } }
/// <summary> /// Adds a new message definition to _messageLevelDict, or updates an existing one /// </summary> /// <param name="levelNumber">Integer code for the message level</param> /// <param name="levelName">Short name for the message level (e.g. "Warn", "Fatal", "Info")</param> /// <param name="messageBoxTitle">Title that will be used in any MessageBox created for this message</param> /// <param name="messageBoxIntro">Intro text that will be used in any MessageBox created for this message</param> /// <param name="windowsErrorLevel">Windows error level, used when creating an event in Event Viewer</param> public static void addMessageDefinition(int levelNumber, string levelName, string messageBoxTitle, string messageBoxIntro, EventLogEntryType windowsErrorLevel) { if (_messageLevelDict == null) { buildDefaultDict(); } MessageLevelDefinition levelDef = new MessageLevelDefinition(); levelDef.levelName = levelName; levelDef.messageBoxTitle = messageBoxTitle; levelDef.messageBoxIntro = messageBoxIntro; levelDef.windowsErrorLevel = windowsErrorLevel; if (_messageLevelDict.ContainsKey(levelNumber)) { _messageLevelDict[levelNumber] = levelDef; } else { _messageLevelDict.Add(levelNumber, levelDef); } }
/// <summary> /// Currently not functional, need an installer to create the Event Viewer source /// Logs an event in the Windows Event Viewer, spawns a message box if this fails /// </summary> /// <param name="messageDef">Definition of the message type</param> /// <param name="error">Exception, if there was one</param> /// <param name="context">Specifies what the application was doing when the error occurred</param> private static void logEventViewerEvent(MessageLevelDefinition messageDef, Exception error, string context) { string eventContent = "Logged at " + DateTime.Now + " (" + DateTime.UtcNow + ") UTC\n\n" + "Error Message: " + error.Message + "\n\n" + "Application error level: " + messageDef.levelName + "\n\n" + "HResult: " + error.HResult + "\n\n" + "Source: " + error.Source + "\n\n" + "TargetSite: " + error.TargetSite + "\n\n" + "Stack Trace:\n" + error.StackTrace; try { if (!EventLog.SourceExists(error.Source)) { EventLog.CreateEventSource(error.Source, "Application"); } EventLog.WriteEntry(error.Source, eventContent, messageDef.windowsErrorLevel); } catch (Exception e) { MessageBox.Show("Unable to log event viewer message: " + e.Message + "\n\n" + eventContent); } }
/// <summary> /// Saves events to the application log file, creating the file if it doesn't exist /// </summary> /// <param name="messageDef">Definition of the message type</param> /// <param name="error">Exception, if there was one</param> /// <param name="context">Specifies what the application was doing when the error occurred</param> private static void logApplicationLogFileEntry(MessageLevelDefinition messageDef, Exception error, string context) { // Confirm the log file location has been specified if (_applicationLogFileLocation == null) { return; } // Create the log file, if it doesn't exist if (!File.Exists(_applicationLogFileLocation)) { try { FileInfo logFileInfo = new FileInfo(_applicationLogFileLocation); Directory.CreateDirectory(logFileInfo.Directory.FullName); XmlDocument newDoc = new XmlDocument(); newDoc.LoadXml("<logs></logs>"); XmlTextWriter xmlWriter = new XmlTextWriter(_applicationLogFileLocation, null); xmlWriter.Formatting = Formatting.Indented; newDoc.Save(xmlWriter); xmlWriter.Dispose(); } catch (Exception e) { MessageBox.Show("Unable to create log file in " + _applicationLogFileLocation + "\n\n" + e.Message); } } // Load the Xml document XmlDocument logFile = new XmlDocument(); logFile.Load(_applicationLogFileLocation); XmlNode rootNode = logFile.SelectSingleNode("logs"); // Build the log entry XmlNode newNode = logFile.CreateElement("log"); XmlAttribute utcTimeAttribute = logFile.CreateAttribute("utctime"); utcTimeAttribute.Value = DateTime.UtcNow.ToString(); newNode.Attributes.Append(utcTimeAttribute); XmlAttribute levelAttribute = logFile.CreateAttribute("level"); levelAttribute.Value = messageDef.levelName; newNode.Attributes.Append(levelAttribute); XmlAttribute contextAttribute = logFile.CreateAttribute("context"); contextAttribute.Value = context; newNode.Attributes.Append(contextAttribute); if (error != null) { newNode.InnerText = error.Message; } else { newNode.InnerText = "No Exception object for event"; } // Append the log entry rootNode.AppendChild(newNode); // Save the log file logFile.Save(_applicationLogFileLocation); }