KB-誰在叫我? .NET程式呼叫歷程的追蹤
1 |
在某些情況下,我們會想知道自己的程式碼被誰所呼叫,例如: 當某個共用函數發生錯誤時,若可知是哪一個類別呼叫這個函數時出錯,將十分有助於Debug。
各位應該都看過.NET Debug Build在出錯時,會顯示所謂的Call Stack(即Exception物件的StackTrace屬性),例如:
那我們可以自己取得這些資訊嗎?
配合System.Diagnostics及System.Reflection的一些類別,這個理想是可能實現的!
我寫了一個簡單的範例:
然後,直接在Console Application呼叫及建立Caller物件後呼叫
可以得到以下的執行結果:
瞧! 我們自己也有能力取得呼叫者的相關資訊。不過,要注意以下幾點:
1. 不管是Debug Build或Release Build,我們都可以取得呼叫者的程序、類別、Method等資料,但必須有.pdb檔時,才能顯示出在哪個原始檔(.cs)的哪一列
2. Debug Build沒有pdb時,無法顯示原始檔及所在程式列。
3. Release Build經設定也可產生pdb。
4. 上述的程式碼中,使用了Reflection的技巧去取得呼叫者資訊,不利於效能,建議節制使用。
各位應該都看過.NET Debug Build在出錯時,會顯示所謂的Call Stack(即Exception物件的StackTrace屬性),例如:
X:\>labs.exe Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at Labs.Program.Lab0818() in F:\Documents and Settings\jeffrey\My Documents\V isual Studio 2005\Projects\Labs\Labs\Program.cs:line 295 at Labs.Program.Main(String[] args) in F:\Documents and Settings\jeffrey\My D ocuments\Visual Studio 2005\Projects\Labs\Labs\Program.cs:line 304 |
那我們可以自己取得這些資訊嗎?
配合System.Diagnostics及System.Reflection的一些類別,這個理想是可能實現的!
我寫了一個簡單的範例:
class Caller { public Caller() { } public void CallIt() { Tracer.ShowCallerInfo("Called by Caller object"); } } class Tracer { public static void ShowCallerInfo(string remark) { Console.Write(new string('=', 80)); Console.WriteLine("Caller Remark: {0}", remark); StackTrace st = new StackTrace(true); StackFrame sf = st.GetFrame(1); MethodBase mb = sf.GetMethod(); Console.WriteLine("Caller Module: {0}",mb.Module.FullyQualifiedName); Console.WriteLine("Caller Class & Method: {0}.{1}()", mb.ReflectedType.FullName, mb.Name); Console.WriteLine("File Info: Line {0} in {1}", sf.GetFileLineNumber(), sf.GetFileName()); Console.WriteLine(); } } |
然後,直接在Console Application呼叫及建立Caller物件後呼叫
static void Lab0818() { Console.WriteLine(calcDiv(1, 0)); Tracer.ShowCallerInfo("Called by main.cs"); Caller c = new Caller(); c.CallIt(); } |
可以得到以下的執行結果:
X:\>labs.exe ================================================================ Caller Remark: Called by main.cs Caller Module: X:\Labs.exe Caller Class & Method: Labs.Program.Lab0818() File Info: Line ================================================================ Caller Remark: Called by Caller object Caller Module: X:\Labs.exe Caller Class & Method: Labs.Caller.CallIt() File Info: Line |
瞧! 我們自己也有能力取得呼叫者的相關資訊。不過,要注意以下幾點:
1. 不管是Debug Build或Release Build,我們都可以取得呼叫者的程序、類別、Method等資料,但必須有.pdb檔時,才能顯示出在哪個原始檔(.cs)的哪一列
2. Debug Build沒有pdb時,無法顯示原始檔及所在程式列。
3. Release Build經設定也可產生pdb。
4. 上述的程式碼中,使用了Reflection的技巧去取得呼叫者資訊,不利於效能,建議節制使用。
Comments
# by wilson
我想請問一下有何方式可以在 unmanged dll 知道Caller 的manged Dll information(如 版本,public key 等等)?