65 votes

Utilisation d'ELMAH dans une application console

Je viens de commencer à utiliser ELMAH et je suis une fan. Mon équipe prend en charge un grand nombre d'applications web et je suis particulièrement heureux qu'ELMAH nous permette de sauvegarder les exceptions de chaque application dans la même table de base de données MS SQL.

Nous prenons également en charge quelques applications de console, DLL et de bureau. Est-il possible d'utiliser la DLL ELMAH pour enregistrer les exceptions dans ces applications au même endroit ?

77voto

Brian Chance Points 801

Nous avions besoin de la possibilité d'enregistrer à partir d'une application console et d'un service Windows en plus de notre site ASP.NET. J'ai utilisé la réponse ( ErrorLog.GetDefault(null); ), ce qui fonctionnait bien jusqu'à ce que j'aie besoin d'envoyer des courriels.

Voici donc ma solution. Elle gère le journal, l'email, le tweet et le filtrage (à la fois dans le fichier de configuration et dans le code). J'ai également enveloppé l'appel principal comme une extension à l'exception afin qu'il puisse être appelé comme : catch(Exception ex) { ex.LogToElmah(); }

Pour filtrer dans le code, accrochez l'événement .Filtering correspondant : 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);
                }
            }
    }
}

En outre, vous devrez ajouter une référence à l'interface de l'entreprise. System.Web.dll dans votre projet pour que cela fonctionne.

EDITAR : Comme indiqué dans les commentaires, ce code enverra des emails uniquement si votre fichier de configuration a <errorMail async="false"/> . Se référer à cet extrait de code si vous voulez garder <errorMail async="true"/> dans votre fichier de configuration (à utiliser lorsque HttpContext.Current est disponible).

68voto

Duke of Muppets Points 865

Nous avons exactement la même situation ici. Nous exécutons ELMAH pour toutes nos applications Web. Quelques-unes d'entre elles ont des programmateurs basés sur la console.

Après avoir fouillé un peu dans le code source, le code suivant semble fonctionner :

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

Le seul vrai problème avec ce qui précède est que vous devez conserver le nom de l'application quelque part dans votre configuration pour être en mesure de voir les entrées sur le visualiseur ELMAH.axd.

Donc, dans notre code de gestion d'erreur générique, nous faisons :

        if (HttpContext.Current != null)
            ErrorSignal.FromCurrentContext().Raise(ex);
        else
        {
            ErrorLog errorLog = ErrorLog.GetDefault(null);
            errorLog.ApplicationName = ErrorHandling.Application;
            errorLog.Log(new Error(ex));
        }

14voto

Jeff Points 4954

Si vous voulez juste envoyer le journal par courriel sans http, vous pouvez faire comme ceci :

    public class MyElmahMail: ErrorMailModule
    {
        public MyElmahMail()
        {
//this basically just gets config from errorMail  (app.config)
            base.OnInit(new HttpApplication());
        }
        public void Log(Error error)
        {
//just send the email pls
            base.ReportError(error);
        }
    }

//to call it
var mail = new MyElmahMail();
mail.Log(new Error(new NullReferenceException()));//whatever exception u want to log

Et en termes d'app.config

//Under configSections
    <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>

Et

  <elmah>
    <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="C:\Elmah.Error" applicationName="MyAwesomeApp" />
    <errorMail from="from@email.com" to="to@email.com" />
  </elmah>

Et les paramètres smtp de votre choix.

Tout est fait. :-)

5voto

Gavin Miller Points 21752

Modifier : Ce CAN être fait - Voir este réponse.


Je suis presque sûr que vous ne pouvez pas faire ça. Je vais essayer de trouver les documents pertinents.

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

D'après ce que je peux trouver en cherchant dans le groupe Google, ce n'est pas possible... Comme ELMAH fonctionne à partir de HttpHandlers (une construction asp.net), il est uniquement ASP.NET.

Cela dit, il est possible de l'utiliser dans une application console. ELMAH fournit une méthode pour lever les erreurs, vous pouvez donc intégrer ELMAH dans votre gestion des exceptions et signaler une erreur par le biais de l'option :

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

Cela impliquerait d'envelopper l'ensemble de votre application dans un gestionnaire d'exceptions et de le signaler. Cela pourrait vous demander quelques ajustements pour y arriver, mais je pense que c'est tout à fait possible.

Au cas où vous en auriez besoin, voici le lien vers le site web de la Commission européenne. Dépôt de code ELMAH .

2voto

Quandary Points 12867

Pour ceux qui ont besoin que la réponse de Brian Chance soit portée à VB.NET :

Imports System
Imports System.Web
Imports Elmah
Namespace System
    Public NotInheritable Class ElmahExtension
        Private Sub New()
        End Sub
        <System.Runtime.CompilerServices.Extension> _
        Public Shared Sub LogToElmah(ex As Exception)
            If HttpContext.Current IsNot Nothing Then
                ErrorSignal.FromCurrentContext().Raise(ex)
            Else
                If httpApplication Is Nothing Then
                    InitNoContext()
                End If
                ErrorSignal.[Get](httpApplication).Raise(ex)
            End If
        End Sub

        Private Shared httpApplication As HttpApplication = Nothing
        Private Shared errorFilter As New ErrorFilterConsole()

        Public Shared ErrorEmail As New ErrorMailModule()
        Public Shared ErrorLog As New ErrorLogModule()
        Public Shared ErrorTweet As New ErrorTweetModule()

        Private Shared Sub InitNoContext()
            httpApplication = New HttpApplication()
            errorFilter.Init(httpApplication)

            TryCast(ErrorEmail, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorEmail)

            TryCast(ErrorLog, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorLog)

            TryCast(ErrorTweet, IHttpModule).Init(httpApplication)
            errorFilter.HookFiltering(ErrorTweet)
        End Sub

    Private Class ErrorFilterConsole
        Inherits Elmah.ErrorFilterModule

        Public Sub HookFiltering([module] As Elmah.IExceptionFiltering)
            AddHandler [module].Filtering, New Elmah.ExceptionFilterEventHandler(AddressOf MyBase.OnErrorModuleFiltering)
        End Sub

    End Class

    End Class
End Namespace

Cependant, pour le simple enregistrement des erreurs dans la base de données, cela sera suffisant :

If System.Web.HttpContext.Current Is Nothing Then
    Dim req As System.Web.HttpRequest = New System.Web.HttpRequest(String.Empty, "https://www.domain.tld", Nothing)
    Dim res As System.Web.HttpResponse = New System.Web.HttpResponse(Nothing)
    System.Web.HttpContext.Current = New System.Web.HttpContext(req, res)

    'Dim request As System.Web.Hosting.SimpleWorkerRequest = New System.Web.Hosting.SimpleWorkerRequest("/blah", "c:\inetpub\wwwroot\blah", "blah.html", Nothing, New System.IO.StringWriter())
    'System.Web.HttpContext.Current = New System.Web.HttpContext(request)

    System.Web.HttpContext.Current.ApplicationInstance = New System.Web.HttpApplication()

    Dim ErrorLog As New Elmah.ErrorLogModule()
    TryCast(ErrorLog, System.Web.IHttpModule).Init(System.Web.HttpContext.Current.ApplicationInstance)
End If

Comme une solution complète :

Public parent As Elmah.ServiceProviderQueryHandler = Nothing

' http://stackoverflow.com/questions/5981750/configuring-elmah-with-sql-server-logging-with-encrypted-connection-string
Public Function Elmah_MS_SQL_Callback(objContext As Object) As System.IServiceProvider
    Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext))
    Dim strConnectionString As String = COR.SQL.MS_SQL.GetConnectionString()

    Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(strConnectionString)
    'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName
    Dim strApplicationName As String = System.Reflection.Assembly.GetExecutingAssembly().FullName
    If Not String.IsNullOrEmpty(strApplicationName) Then
        log.ApplicationName = strApplicationName.Substring(0, strApplicationName.IndexOf(","))
    End If

    container.AddService(GetType(Elmah.ErrorLog), log)
    Return container
End Function ' Elmah_MS_SQL_Callback

Public Function Elmah_PG_SQL_Callback(objContext As Object) As System.IServiceProvider
    Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext))
    Dim strConnectionString As String = COR.SQL.MS_SQL.GetConnectionString()

    Dim log As Elmah.PgsqlErrorLog = New Elmah.PgsqlErrorLog(strConnectionString)
    'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName
    Dim strApplicationName As String = System.Reflection.Assembly.GetExecutingAssembly().FullName
    If Not String.IsNullOrEmpty(strApplicationName) Then
        log.ApplicationName = strApplicationName.Substring(0, strApplicationName.IndexOf(","))
    End If

    container.AddService(GetType(Elmah.ErrorLog), log)
    Return container
End Function ' Elmah_PG_SQL_Callback

' http://weblogs.asp.net/stevewellens/archive/2009/02/01/debugging-a-deployed-site.aspx
Public Sub Initialize()

    If System.Web.HttpContext.Current Is Nothing Then
        Dim req As System.Web.HttpRequest = New System.Web.HttpRequest(String.Empty, "https://www.domain.tld", Nothing)
        Dim res As System.Web.HttpResponse = New System.Web.HttpResponse(Nothing)
        System.Web.HttpContext.Current = New System.Web.HttpContext(req, res)

        'Dim request As System.Web.Hosting.SimpleWorkerRequest = New System.Web.Hosting.SimpleWorkerRequest("/blah", "c:\inetpub\wwwroot\blah", "blah.html", Nothing, New System.IO.StringWriter())
        'System.Web.HttpContext.Current = New System.Web.HttpContext(request)

        System.Web.HttpContext.Current.ApplicationInstance = New System.Web.HttpApplication()

        Dim ErrorLog As New Elmah.ErrorLogModule()
        TryCast(ErrorLog, System.Web.IHttpModule).Init(System.Web.HttpContext.Current.ApplicationInstance)
    End If

    parent = Elmah.ServiceCenter.Current

    If SQL.IsMsSql Then
        Elmah.ServiceCenter.Current = AddressOf Elmah_MS_SQL_Callback
    End If

    If SQL.IsPostGreSql Then
        Elmah.ServiceCenter.Current = AddressOf Elmah_PG_SQL_Callback
    End If
End Sub ' InitializeElmah

Et

Elmah.ErrorSignal.FromCurrentContext().Raise(New NotImplementedException("Test"))

fonctionnera si elle est appelée après Initialize()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X