Using ELMAH in a console application

Michael La Voie picture Michael La Voie · May 8, 2009 · Viewed 26.2k times · Source

I just started using ELMAH and am a fan. My team supports a large number of web applications and I'm particularly excited that ELMAH lets us save exceptions from each application to the same MS SQL database table.

We also support a few console, DLL and desktop applications. Is it possible to use the ELMAH DLL to log exceptions in these apps to that same location?

Answer

Brian Chance picture Brian Chance · Mar 18, 2010

We needed the ability to log from a console app and a windows service in addition to our ASP.NET site. I used the answer (ErrorLog.GetDefault(null);) which worked well until I needed to email too.

So, here is my solution. It handles the log, email, tweet and filtering (both in the config file and in code). I have also wrapped the main call as an extension to Exception so it can be called like: catch(Exception ex) { ex.LogToElmah(); }

To filter in code, hook the corresponding .Filtering event: ElmahExtension.ErrorLog.Filtering += new ExceptionFilterEventHandler(ErrorLog_Filtering);

Code:

using System;
using System.Web;
using Elmah;
namespace System
{
    public static class ElmahExtension
    {
        public static void LogToElmah(this Exception ex)
        {
            if (HttpContext.Current != null)
            {
                ErrorSignal.FromCurrentContext().Raise(ex);
            }
            else
            {
                if (httpApplication == null) InitNoContext();
                ErrorSignal.Get(httpApplication).Raise(ex);
            }
        }

            private static HttpApplication httpApplication = null;
            private static ErrorFilterConsole errorFilter = new ErrorFilterConsole();

            public static ErrorMailModule ErrorEmail = new ErrorMailModule();
            public static ErrorLogModule ErrorLog = new ErrorLogModule();
            public static ErrorTweetModule ErrorTweet = new ErrorTweetModule();

            private static void InitNoContext()
            {
                httpApplication = new HttpApplication();
                errorFilter.Init(httpApplication);

                (ErrorEmail as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorEmail);

                (ErrorLog as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorLog);                

                (ErrorTweet as IHttpModule).Init(httpApplication);
                errorFilter.HookFiltering(ErrorTweet);
            }

            private class ErrorFilterConsole : ErrorFilterModule
            {
                public void HookFiltering(IExceptionFiltering module)
                {
                    module.Filtering += new ExceptionFilterEventHandler(base.OnErrorModuleFiltering);
                }
            }
    }
}

In addition, you will need to add a reference to the System.Web.dll in your project for this to work.

EDIT: As per the comments, this code will send emails only if your config file has <errorMail async="false"/>. Refer to this code snippet should you want to keep <errorMail async="true"/> in your config file (to be used when HttpContext.Current is available).