前言
作為一個程序員,你的相當一部分時間可能會用在調試。不知道大家是否同意,異常處理(Exception Handling)是一個看似簡單,但是又極難做好的工作。當然,現在已經有一些業界經驗以及框架(例如Enterprise Library中的Exception Handling Application Block)可供參考和使用,這些框架可以幫助我們較為靈活地配置,處理或者記錄異常。我今天要跟大家分享的一個話題是,如何在記錄異常的時候,包含源代碼文件名和行號等有用信息。如果有這些信息,我們將能更加簡單地定位到問題所在。
案例演示
為了講解這個內容,我准備了一個簡單的項目來做演示,如下所示
實際上,這個Solution中有兩個項目,一個是作為組件的ClassLibrarySample
1: using System;
2:
3: namespace ClassLibrarySample
4: {
5: public class Test
6: {
7: public void MyMethod(int a, int b) {
8: try
9: {
10: Console.WriteLine(b/a);
11: }
12: catch (Exception ex)
13: {
14: Console.WriteLine(ex.Message);
15: }
16: }
17: }
18: }
另一個是作為調用程序的ConsoleApplicationSample
1: using System;
2:
3: namespace ConsoleApplicationSample
4: {
5: class Program
6: {
7: static void Main(string[] args)
8: {
9: var t = new ClassLibrarySample.Test();
10: t.MyMethod(0, 1);//這個調用會出錯,因為會發生除零錯誤
11: Console.Read();
12: }
13: }
14: }
這個程序運行起來肯定就是會報告異常,然后被捕捉到,我們在主程序上面可以看到如下的輸出
我們都知道,這樣的異常消息可能對我們幫助不是很大,尤其是如果源文件中代碼有成百上千行,那么如果不能快速定位到可能是哪一行出了這個異常,那么看起來調試和排錯都會很難。
那么是否有辦法在異常消息中,得到源代碼文件的一些信息呢?事實上是可以做到的,你只要像下面這樣修改即可:使用了StackTrace這個類型
1: using System;
2: using System.Diagnostics;
3:
4: namespace ClassLibrarySample
5: {
6: public class Test
7: {
8: public void MyMethod(int a, int b) {
9: try
10: {
11: Console.WriteLine(b/a);
12: }
13: catch (Exception ex)
14: {
15: Console.WriteLine(ex.Message);
16: //通過如下代碼來記錄異常詳細的信息
17: var trace = new StackTrace(ex, true).GetFrame(0);
18: Console.WriteLine("文件名:{0},行號:{1},列號:{2}", trace.GetFileName(), trace.GetFileLineNumber(), trace.GetFileColumnNumber());
19: }
20: }
21: }
22: }
這樣一來,我們再進行調試的時候,就可以看到更加詳細的信息了。
大家可能會很好奇,這個信息是怎么給我們的呢?其實,要想實現這個功能,必須滿足一個前提條件,就是必須有ClassLibrarySample這個組件對應的調試符號文件(pdb)。
如果我將這個文件刪除掉,會怎么樣呢?
我們看到,如果沒有pdb文件,則輸出的信息是空白的。
所以,如果你想使用這個技術來記錄這些與源代碼有關的詳細信息,需要確保在部署應用程序的時候,將有關組件的pdb文件也一起部署。
如果是私有部署的話,那么要做到這一點是不難的,打包的時候,將pdb文件一起包含進去就可以了。但如果這個組件是公有部署(部署到GAC) 的話,就需要額外的一些步驟。
為了將程序集部署到GAC,我們首先需要對其進行強名稱簽名。
然后,通過gacutil這個命令行工具,可以手工地將其添加到GAC中
接下來,為了讓主程序使用GAC中這個組件,而不是程序根目錄下面的那個。我們需要對引用做一個設置:Copy local設置為false
再次運行主程序的話,我們會得到如下的輸出
還是沒有與源代碼有關的詳細信息,這是因為注冊到GAC的程序集默認都是沒有pdb文件的。他們一般在下面這樣的目錄里面
【備注】.NET Framework 4.0這個版本中對於GAC的路徑做了調整,不再是原先的c:\windows\assembly目錄了
所以,如果需要的話,你可以將pdb文件,手工(或者通過腳本)復制到這個目錄,例如
這樣的話,就可以在運行主程序的時候,得到與源代碼有關的詳細信息了。