2010-08-09 89 views

回答

2

除了Exception?我只需將我的日誌記錄模塊添加到我的catch塊中即可。

喜歡的東西:

catch(YourException ex) 
{ 
    LogMyException(ex, [otherParamsYouNeed]); 
    //Other Exception Handling 
} 

如果你想記錄的東西,無論成功或失敗的狀態,使用finally{}

1

在WinForms中,您有Application.ThreadException事件,更一般的情況是AppDomain.CurrentDomain.UnhandledException事件。

但請注意,在記錄這些異常之後,建議的操作是關閉應用程序。它可能不再處於穩定狀態。

+0

+1這些處理程序是記錄未處理異常的最佳位置,將導致應用程序終止。我認爲這比'log and rethrow'更接近故障點,因爲.NET Exception類已經保留了像StackTrace這樣的上下文信息。 – 2010-08-09 14:49:36

1

AppDomain類有一個UnhandledException事件,但我不認爲你可以訂閱任何異常被拋出。

6

是的 - 這裏是AppDomain對象的UnhandledException事件:

AppDomain.CurrentDomain.UnhandledException += YourHandler 

FYI:您應該只使用這些處理器作爲最後的手段 - 這是遠不如趕在trycatch塊例外,雖然這可能並不總是可能的(例如在第三方代碼開始新線程的情況下)

此外,只有當例外情況是未處理時纔會觸發此事件 - 據我所知,沒有辦法存在通過這種方式通知捕獲的事件,而無需將調試器附加到流程中。

+0

對於「你應該只使用這些處理程序作爲最後的手段」+1,我使用它來記錄異常,通知用戶並僅重新啓動應用程序。否則,你可能會遇到各種各樣的問題。 – 2010-08-09 15:52:20

+0

從文檔中不清楚,但看起來好像訂閱此事件讓您有機會阻止AppDomain的關閉。 – 2010-08-09 15:55:56

0

在ASP.NET中,通過處理應用程序錯誤事件,可以通過處理Page_Error事件或應用程序級別(在global.asax或IHttpModule實現中)在頁面級別捕獲未處理的異常。這些事件不會給你實際的異常,所以你需要調用服務器來得到異常:

Exception ex = HttpContext.Current.Server.GetLastError(); 
4

你應該看看這樣做有PostSharp一些面向方面的編程,你可以寫一個簡單的日誌屬性並將其應用於整個程序集。

所有你需要的是這樣的:

[Serializable] 
public class LogAttribute : OnMethodInvocationAspect 
{ 
    public override void OnInvocation(MethodInvocationEventArgs eventArgs) 
    { 
     try 
     { 
     eventArgs.Proceed(); 
     } 
     catch(Exception ex) 
     { 
     // log exception here 
     } 
    } 
} 

並將其應用到您的程序集:

[assembly: Log] 
public class ... 

這不是茶,每個人的杯子,但我發現這是一個非常乾淨,整潔的方式來避免在我的課程中做大量的樣板代碼,並讓我能夠開發更多與項目本身相關的功能。

更新:作爲庫格爾在評論中指出,這將幫助您跟蹤和記錄方法的執行過程中引發的任何異常,但如果你想登錄國家內部,您需要的方法做比這更多的工作。例如,你可能仍然需要在你的方法中使用try/catch塊,你可以用它來捕獲你的類感興趣的異常,甚至可以把它們包裝在一個自定義的異常對象中,這樣你就可以開始添加更多有用的信息就像錯誤代碼等。只要你的自定義異常有一個適當的機制來設置它的'消息'屬性,例如

public class DictionaryKeyNotValidException() : Exception 
{ 
    public DictionaryKeyNotValidException(string key) 
     : base(GetMessage(key)) 
    { 
    } 

    public ErrorEnum ErrorCode { get { return ErrorEnum.InvalidDictionaryKey; } } 

    private string GetMessage(string key) 
    { 
     return string.Format("ERROR {0} : Invalid dictionary key encountered {1}", 
          ErrorCode.GetHashCode(), key); 
    } 
} 

那麼在您的日誌屬性,只要你正在使用log4net的,你就可以開始記錄更多有用信息:

catch (Exception ex) 
{ 
    // log error 
    log.Error(ex); 

    // handle exception, rethrow, etc. 
    ... 
} 

抱歉,這變得有點長篇大論..

+0

如果你想在一個方法內記錄一個狀態,這不會對你有所幫助。 – Kugel 2010-08-09 14:46:12

+1

記錄後請確保包含'throw;'。 – 2010-08-09 14:51:32

0

要延長burningmonk給出的答案,你也可以嘗試使用log4PostSharp。這是預建的代碼,它使用PostSharp來插入與log4net日誌框架一起工作的日誌代碼。

此外,它會自動將代碼添加到捕獲異常並記錄它們的方法中。

這一切都取決於您是否樂意使用log4net日誌記錄框架或更願意自己做。

0

在vb.net中,可以在catch語句中添加一個「When」限定詞(例如,當Ex.Message.Contains(「Sorry」))時,將Catch Ex添加爲ObjectDisposedException。這可以用於日誌記錄(例如'當日志記錄失敗時返回異常',不會捕獲任何異常,但會將它們全部記錄下來),並且看起來像是在C#中有用的功能。最後我聽說,該功能僅在vb.net中可用(不確定如果在vb.net中使用這種功能編譯代碼並反編譯爲C#)會發生什麼情況。

+0

這是正確的:它是C#不公開的CLR特性之一。你可以通過捕獲所有ObjectDisposedException來檢查它們的Message,然後用'throw;'重新拋出一些非常類似的東西,如果這不是你想要的。不知道它在性能上的表現如何,但是再一次,這是一個例外,所以誰在乎呢? – 2010-08-09 15:52:43

+0

@Steven Sudit:調試時,未捕獲的異常會在執行的地方拋出;一個被捕捉和被重新拋出的異常會在被重新拋出的地方破壞執行。 – supercat 2010-08-11 04:31:30

+0

我不能否認在調試器下運行時存在差異,但我不寫我的代碼,以便有未捕獲的異常。在最壞的情況下,頂級catch塊會記錄並退出。 – 2010-08-11 13:49:36

0

您可以在Global.asax Application_Error事件中添加一些內容。

我已經使用此方法來完成您在原始文章中描述的內容,記錄錯誤並通過電子郵件發送通知。

相關問題