Kirk Evans Blog

.NET From a Markup Perspective

A Better ExceptionXmlPublisher for the Exception Management Application Block.

This snippet incorporates part of a post from microsoft.public.dotnet.framework.  It shows how to allow multiple threads to write to the same file at once, using a mutex to provide concurrency.  This example is integrated with the Exception Management Block to provide a means of logging errors in multi-user applications to XML files.

using System;
using System.Text;
using System.IO;
using System.Xml; 
using System.Collections;
using System.Collections.Specialized;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using System.Threading;
using System.Diagnostics;

namespace DistributedArchitects.Exceptions
{
 /// <SUMMARY>
 /// Logs the XML data to the specified file.
 /// </SUMMARY>
 public class ExceptionXmlPublisher : IExceptionXmlPublisher
 {
  /// <SUMMARY>
  /// Called by ExceptionManager through IExceptionXmlPublisher interface. 
  /// </SUMMARY>
  /// <PARAM name=”ExceptionInfo”> The XML DOM object containing the exception information</PARAM>
  /// <PARAM name=”ConfigSettings”> Configuration settings from the *.config file for this publisher. Requires the
  /// fileName configuration attribute within the *.config file entry.</PARAM>
  void IExceptionXmlPublisher.Publish(XmlDocument ExceptionInfo, NameValueCollection ConfigSettings)
  {
   OnPublish(ExceptionInfo,ConfigSettings);
  }

  /// <SUMMARY>
  /// Overrideable implementation of IExceptionXmlPublisher.Publish interface method.  Writes the
  /// exception to file, using a mutex to allow for concurrent write operations to be
  /// synchronized. 
  /// </SUMMARY>
  /// <PARAM name=”ExceptionInfo”> The XML DOM object containing the exception information</PARAM>
  /// <PARAM name=”ConfigSettings”> Configuration settings from the *.config file for this publisher.  Requires the
  /// fileName configuration attribute within the *.config file entry.</PARAM>
  protected virtual void OnPublish(XmlDocument exceptionInfo, NameValueCollection configSettings)
  {      
   string fileName;
   if (configSettings != null)
   {
    fileName = configSettings[“fileName”];
   }
   else
   {
    fileName = @”C:\ErrorLog.xml”;
   }
   
   Mutex mutex = new Mutex(false, “mymutex.blah.blah”);
   if (!mutex.WaitOne())
   {
    //TODO:  What to do with the error if this block fails? 
    // For now, log to event log and swallow the error.
    EventLog log = new EventLog(“ErrorLog”);;
    try
    {     
     if(!EventLog.SourceExists(“debugging”))
     {
      EventLog.CreateEventSource(“debugging”, “ErrorLog”);
     }     
     log.Source = “debugging”;
     log.WriteEntry(“Unable to create mutex in ExceptionXmlPublisher.”,System.Diagnostics.EventLogEntryType.Error);
     return;
    }
    finally
    {
     log.Dispose();     
    }
   }

   try
   {
    using (FileStream fs =  File.Open(fileName, FileMode.Append ,FileAccess.Write,FileShare.Write ) )
    {                           
     StreamWriter writer = new StreamWriter(fs);
     writer.Write(exceptionInfo.OuterXml);
     writer.Flush();
    }
   }
   finally
   {
    mutex.ReleaseMutex();
   }   
  }
 }
}

<Kirk />