views:

879

answers:

4

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?

+2  A: 

I'm pretty sure you can't do this. I'll try and dig up the relevant material.

http://groups.google.com/group/elmah/browse_thread/thread/f214c4f782dc2bf4/d96fe43b60765f0c?lnk=gst&q=app#d96fe43b60765f0c

So from what I can find searching the Google group is that it's not possible... Since ELMAH works off of HttpHandlers (an asp.net construct) it is ASP.NET only.

With that said, there are ways that you could utilize it on a console application. ELMAH provides a method to raise errors, so you could wrap ELMAH in your exception handling and then signal an error via:

ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());

This would mean wrapping your entire application in an exception handler and signaling. It might take you some tweaking to get it down, but I think it's totally possible.

In case you require it, this is the link to the ELMAH code repository.

Gavin Miller
Thank you. I understand that it wasn't build around this, but it seems like a need others might have, to share a common error db
Michael La Voie
+8  A: 

We have exactly the same situation here. Running ELMAH for all our web applications. A few of them have console based schedulers.

After doing some digging through the source code, the following code seems to work:

            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = "/LM/W3SVC/1/ROOT/AppName";
            errorLog.Log(new Error(ex));

The only real problem with the above is that you need to keep the application name somewhere in your config to be able to see the entries on the ELMAH.axd viewer.

So in our generic error handling code we do:

        if (HttpContext.Current != null)
            ErrorSignal.FromCurrentContext().Raise(ex);
        else
        {
            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = ErrorHandling.Application;
            errorLog.Log(new Error(ex));
        }
Duke of Muppets
Very cool, I'll try this out.
Michael La Voie
Hmm - pretty cool, but I can't seem to get it to send emails when the error occurs in the console app. Any ideas?
teedyay
Unlikely, the errorLog.Log seems to bypass all the other listeners. Anyone know any better?
Duke of Muppets
+1  A: 

ELMAH stands for Error Logging Modules and Handlers - referring, of course, to IHttpModule and IHttpHandler.

Console applications do not use HTTP, so would typically not be able to benefit much from Modules and Handlers built for HTTP.

Justice
A: 

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);
                }
            }
    }
}
Brian Chance