Utiliser ELMAH dans une application console

Je viens de commencer à utiliser ELMAH et je suis fan. Mon équipe prend en charge un grand nombre d’applications Web et je suis particulièrement ravi qu’ELMAH nous permette de sauvegarder des exceptions pour chaque application sur la même table de firebase database MS SQL.

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

Nous avons exactement la même situation ici. Lancer ELMAH pour toutes nos applications Web. Quelques-uns d’entre eux ont des ordonnanceurs basés sur la console.

Après quelques recherches 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 problème réel avec ce qui précède est que vous devez conserver le nom de l’application quelque part dans votre configuration pour pouvoir voir les entrées du visualiseur ELMAH.axd.

Donc, dans notre code de gestion des erreurs 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)); } 

Nous avions besoin de la possibilité de se connecter depuis une application console et un service Windows en plus de notre site ASP.NET. J’ai utilisé la réponse ( ErrorLog.GetDefault(null); ) qui a bien fonctionné jusqu’à ce que j’aie aussi besoin d’envoyer un email.

Alors, voici ma solution. Il gère le journal, l’e-mail, le tweet et le filtrage (à la fois dans le fichier de configuration et dans le code). J’ai également inclus l’appel principal en tant qu’extension d’Exception afin qu’il puisse être appelé comme: catch(Exception ex) { ex.LogToElmah(); } catch(Exception ex) { ex.LogToElmah(); }

Pour filtrer le code, connectez 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 append une référence à System.Web.dll dans votre projet pour que cela fonctionne.

EDIT : selon les commentaires, ce code enverra des emails seulement si votre fichier de configuration a . Reportez-vous à cet extrait de code si vous souhaitez conserver dans votre fichier de configuration (à utiliser lorsque HttpContext.Current est disponible).

Si vous voulez simplement envoyer le journal 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 de app.config

 //Under configSections  

Et

      

Et les parameters smtp de votre choix.

Terminé. 🙂

Edit : Ce CAN peut être fait – Voir cette réponse.


Je suis sûr que tu ne peux pas faire ça. Je vais essayer de trouver le matériel pertinent.

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

Donc, d’après ce que je peux trouver, la recherche dans le groupe Google est que ce n’est pas possible … Puisque ELMAH fonctionne à partir de HttpHandlers (une construction asp.net), il s’agit uniquement d’ASP.NET.

Cela dit, il existe des moyens que vous pouvez utiliser sur une application console. ELMAH fournit une méthode pour générer des erreurs, vous pouvez donc envelopper ELMAH dans votre gestion des exceptions et signaler une erreur via:

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

Cela signifierait d’envelopper l’ensemble de votre application dans un gestionnaire d’exceptions et une signalisation. Cela pourrait vous demander quelques ajustements, mais je pense que c’est tout à fait possible.

Si vous en avez besoin, c’est le lien vers le référentiel de code ELMAH .

Pour ceux qui ont besoin de la réponse de Brian Chance porté sur VB.NET:

 Imports System Imports System.Web Imports Elmah Namespace System Public NotInheritable Class ElmahExtension Private Sub New() End Sub  _ 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 ne consigner que des erreurs dans la firebase database, cela suffira:

 If System.Web.HttpContext.Current Is Nothing Then Dim req As System.Web.HttpRequest = New System.Web.HttpRequest(Ssortingng.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.SsortingngWriter()) '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 solution complète:

 Public parent As Elmah.ServiceProviderQueryHandler = Nothing ' http://stackoverflow.com/questions/5981750/configuring-elmah-with-sql-server-logging-with-encrypted-connection-ssortingng Public Function Elmah_MS_SQL_Callback(objContext As Object) As System.IServiceProvider Dim container As New System.ComponentModel.Design.ServiceContainer(parent(objContext)) Dim strConnectionSsortingng As Ssortingng = COR.SQL.MS_SQL.GetConnectionSsortingng() Dim log As Elmah.SqlErrorLog = New Elmah.SqlErrorLog(strConnectionSsortingng) 'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName Dim strApplicationName As Ssortingng = System.Reflection.Assembly.GetExecutingAssembly().FullName If Not Ssortingng.IsNullOrEmpty(strApplicationName) Then log.ApplicationName = strApplicationName.Subssortingng(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 strConnectionSsortingng As Ssortingng = COR.SQL.MS_SQL.GetConnectionSsortingng() Dim log As Elmah.PgsqlErrorLog = New Elmah.PgsqlErrorLog(strConnectionSsortingng) 'Dim strApplicationName = System.Web.Compilation.BuildManager.GetGlobalAsaxType().BaseType.Assembly().FullName Dim strApplicationName As Ssortingng = System.Reflection.Assembly.GetExecutingAssembly().FullName If Not Ssortingng.IsNullOrEmpty(strApplicationName) Then log.ApplicationName = strApplicationName.Subssortingng(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(Ssortingng.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.SsortingngWriter()) '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 s’il est appelé après Initialize ()

Eh bien, puisque je ne peux pas faire de commentaire, je posterai ça ici et peut-être que quelqu’un le verra.

Après avoir suivi la méthode de Brian et les commentateurs, j’ai réussi à faire fonctionner le courrier électronique, mais je ne voyais toujours pas les messages SQL enregistrés, même si j’avais défini le nom de l’application. Ce que je ne réalisais pas, c’est qu’ils étaient en train de se connecter, mais je ne les voyais pas car le nom de l’application doit être le même que votre fichier web.config pour pouvoir le voir.

Mon web.config n’a pas spécifié applicationName, donc “/ LM / W3SVC / 2 / ROOT” était défini par défaut, ce qui est en gros ce que “asgeo1” a commenté, même si je n’avais pas réalisé que ce devait être la même chose.

Comme je n’avais pas vraiment d’erreurs, j’ai configuré applicationName dans mon site web.config et mon app.config pour qu’ils soient identiques et maintenant tout se présente comme un champion.

  

ELMAH signifie «Error Logging Modules and Handlers» (modules de gestion des erreurs et gestionnaires), en référence bien sûr à IHttpModule et IHttpHandler .

Les applications de console n’utilisent pas HTTP, de sorte que les modules et les gestionnaires construits pour HTTP ne seraient généralement pas très utiles.