我刚开始使用ELMAH,感到非常满意。我的团队支持大量的Web应用程序,我特别兴奋的是ELMAH可以让我们将每个应用程序的异常保存到同一个MS SQL数据库表。
我们还支持一些控制台、DLL和桌面应用程序。是否可以使用ELMAH DLL将这些应用程序中的异常记录到同一位置?
我刚开始使用ELMAH,感到非常满意。我的团队支持大量的Web应用程序,我特别兴奋的是ELMAH可以让我们将每个应用程序的异常保存到同一个MS SQL数据库表。
我们还支持一些控制台、DLL和桌面应用程序。是否可以使用ELMAH DLL将这些应用程序中的异常记录到同一位置?
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"/>
时发送电子邮件。如果您想保留配置文件中的<errorMail async="true"/>
(当HttpContext.Current可用时使用),请参考此代码片段。
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="elmah-sqlserver" applicationName="/LM/W3SVC/3/ROOT" />
。 - asgeo1errorlog
设置添加到App.config中。还需要做其他事情吗?
此外,我无法在主项目的Web.Config中找到applicationName
,以便将其包含在控制台应用程序的App.config中。 - Shyamal Parikh我们这里的情况与你们完全相同。在所有Web应用程序中运行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));
}
System.Web
Dll。 - Joy 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设置。
全部完成。:-)
编辑:这是可以做到的 - 请参见this答案。
我确信你做不到这件事。我会尽力找到相关材料。
根据我在谷歌组中搜索到的信息,似乎不可能实现...由于ELMAH是基于HttpHandlers(一种asp.net结构),所以只能在ASP.NET上使用。
话虽如此,你仍然可以在控制台应用程序中利用它。ELMAH提供了一种引发错误的方法,因此你可以将ELMAH包装在异常处理中,然后通过以下方式发出错误信号:
ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
好的,既然我不能评论,那我就在这里发帖,也许有人会看到。
在遵循Brian的方法和评论者的建议后,我成功地使电子邮件工作了,但我仍然没有看到SQL消息被记录,尽管我已经设置了applicationName。我没有意识到它们实际上已经被记录了,只是因为applicationName必须与您的web.config相同才能查看它。
我的web.config没有指定applicationName,所以它默认为“/LM/W3SVC/2/ROOT”,这基本上就是“asgeo1”评论的内容,尽管我没有意识到它必须是相同的。
由于我真的没有任何错误需要关注,所以我在我的web.config和app.config中配置了相同的applicationName,现在一切都像冠军一样显示出来了。
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="MyAppName" />
对于那些需要将Brian Chance的答案移植到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
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
' https://dev59.com/cFfUa4cB1Zd3GeqPEyHF
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()之后才能起作用。
ELMAH代表错误日志模块和处理程序 - 当然是指IHttpModule
和IHttpHandler
。
控制台应用程序不使用HTTP,因此通常无法从为HTTP构建的模块和处理程序中受益太多。