IT Share you

콘솔 애플리케이션에서 ELMAH 사용

shareyou 2020. 11. 16. 23:11
반응형

콘솔 애플리케이션에서 ELMAH 사용


방금 ELMAH를 사용하기 시작했고 팬입니다. 우리 팀은 많은 웹 응용 프로그램을 지원하며 특히 ELMAH를 사용하여 각 응용 프로그램의 예외를 동일한 MS SQL 데이터베이스 테이블에 저장할 수있게되어 매우 기쁩니다.

또한 몇 가지 콘솔, DLL 및 데스크톱 응용 프로그램을 지원합니다. ELMAH DLL을 사용하여 이러한 앱의 예외를 동일한 위치에 기록 할 수 있습니까?


우리는 여기서 똑같은 상황을 가지고 있습니다. 모든 웹 애플리케이션에 대해 ELMAH를 실행합니다. 그들 중 일부는 콘솔 기반 스케줄러를 가지고 있습니다.

소스 코드를 살펴본 후 다음 코드가 작동하는 것 같습니다.

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

위의 유일한 문제는 ELMAH.axd 뷰어에서 항목을 볼 수 있도록 구성 어딘가에 애플리케이션 이름을 유지해야한다는 것입니다.

따라서 일반적인 오류 처리 코드에서 다음을 수행합니다.

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

ASP.NET 사이트 외에도 콘솔 앱 및 Windows 서비스에서 로그하는 기능이 필요했습니다. 나는 ErrorLog.GetDefault(null);이메일을 보내야 할 때까지 잘 작동 하는 대답 ( )을 사용했습니다.

그래서 여기 내 해결책이 있습니다. 로그, 이메일, 트윗 및 필터링을 처리합니다 (구성 파일과 코드 모두에서). 또한 메인 호출을 Exception에 대한 확장으로 래핑하여 다음과 같이 호출 할 수 있습니다.catch(Exception ex) { ex.LogToElmah(); }

코드에서 필터링하려면 해당 .Filtering 이벤트를 연결합니다. ElmahExtension.ErrorLog.Filtering += new ExceptionFilterEventHandler(ErrorLog_Filtering);

암호:

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

또한 System.Web.dll이 작업을 수행하려면 프로젝트에에 대한 참조를 추가해야합니다 .

편집 : 의견에 따라이 코드는 구성 파일에 <errorMail async="false"/>. HttpContext.Current를 사용할 수있을 때 사용하기 위해 구성 파일 에 보관 하려면 이 코드 조각을 참조하십시오 <errorMail async="true"/>.


http없이 로그를 이메일로 보내려면 다음과 같이 할 수 있습니다.

    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

그리고 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>

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

그리고 원하는 smtp 설정.

모두 완료되었습니다. :-)


편집 : 이것은 할 있습니다- 답변을 참조하십시오 .


나는 당신이 이것을 할 수 없다고 확신합니다. 관련 자료를 찾아 보겠습니다.

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

그래서 내가 찾을 수있는 구글 그룹 검색은 불가능하다는 것입니다. ELMAH는 HttpHandlers (asp.net 구조)에서 작동하기 때문에 ASP.NET 전용입니다.

즉, 콘솔 응용 프로그램에서 사용할 수있는 방법이 있습니다. ELMAH는 오류를 발생시키는 방법을 제공하므로 예외 처리에서 ELMAH를 래핑 한 다음 다음을 통해 오류 신호를 보낼 수 있습니다.

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

이는 전체 애플리케이션을 예외 처리기 및 신호로 래핑하는 것을 의미합니다. 그것을 내리기 위해 약간의 조정이 필요할 수 있지만 나는 그것이 완전히 가능하다고 생각합니다.

필요한 경우 ELMAH 코드 저장소에 대한 링크 입니다.


VB.NET으로 이식 된 Brian Chance의 답변이 필요한 사람들을 위해 :

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

그러나 데이터베이스에 오류를 기록하는 것만으로는 충분합니다.

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

완전한 솔루션 :

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

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

Initialize () 후에 호출되면 작동합니다.


글쎄요, 제가 댓글을 달 수 없기 때문에 여기에이 글을 게시하고 누군가가 볼 수있을 것입니다.

After following Brian's method and the commentors I was able to get email working but I still wasn't seeing the SQL messages being logged, even though I had set the applicationName. What I didn't realize is that they were actually being logged I just wasn't seeing them because the applicationName must be the same as your web.config in order to be able to view it.

My web.config didn't have applicationName specified, so it was defaulting to "/LM/W3SVC/2/ROOT", which is basically what "asgeo1" commented, though I didn't realize it had to be the same.

Since I didn't really have any errors I was concerned with, I configured applicationName in my web.config and my app.config to be the same and now everything shows up like a champ.

<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="MyAppName" />

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.

참고URL : https://stackoverflow.com/questions/841451/using-elmah-in-a-console-application

반응형