2012-11-19 29 views
4

我想實現更復雜的錯誤處理。爲了實現我的目標,我需要從curent StackTrace中過濾出非用戶代碼方法(框架)。從StackTrace中篩選出非用戶代碼方法

在ASP.NET典型的StackTrace中,你可能會猜測許多方法對於調試目的來說是非常不相關的,因爲它們在用戶代碼之外。視覺工作室給你選擇過濾出這個非用戶代碼(幀),所以我猜它是可能的。然而,在探索StackFrames(和方法,模塊,程序集......)的方法和屬性大約30分鐘後,我找不到任何可用於識別「系統」框架的東西。

我已經結束了手動指定要登錄哪些模塊(模塊是程序集的一部分,在我的案例中是1:1)。

有沒有更好的方法來做到這一點?只需包含核心ASP.NET之外的所有內容

回答

5

StackFrame類有GetMethod()成員函數,從檢索MethodBase對象。

如果你需要的是一個樸素濾波可能會執行下列操作之一:

  • 地帶出在開頭一類的每一個方法「系統」。或「微軟」。 (因爲所有的.NET庫都放在那裏)。
  • 查找方法所在的組件(請參閱前向),然後檢查AssemblyCompanyAttribute和「Microsoft Corporation」製造的過濾器組件)。這比以前的方法更好,因爲有時候我看到了將自己的類型放在System命名空間中的庫。

如果您需要更多的東西,您可以在定義該方法的地方獲得模塊(MethodBase.Module)。現在你有兩個選擇:

  • 如果你所有的組件簽署你可以只顯示與公共密鑰令牌(獲得其中模塊與Module.Assembly屬性定義的裝配方法,建立與Assembly.FullNameAssemblyName對象,然後檢查AssemblyName.KeyPair屬性的公鑰,它必須匹配你的公鑰標記(簡單地與GetExecutingAssembly()比較)
  • 如果不是所有你的程序集都簽了名,你可以做同樣的操作,但是過濾掉所有與公鑰標記匹配的程序集系統程序集(這可能是最簡單的情況,它也會包含第三部分庫)

請注意,並非所有系統組件具有相同的公鑰標記(即使在同一Framework版本),所以你必須收集和檢查關鍵字的列表(只是瀏覽c:\windows\assembly讀取它們)。一個好方法是檢查公鑰,然後使用AssemblyCompanyAttribute應用第二個過濾器。

+0

謝謝!我想沒有直接的方法來做到這一點(類似IsSystem屬性),儘管你的建議非常接近。天真和更復雜的方法似乎很合理。我對彙編簽名不是很有經驗,但是系統程序集總是擁有相同的公鑰令牌,而不管它們的版本是什麼? – NeverStopLearning

+1

不,不是所有程序集(即使在同一版本中)都有相同的公鑰令牌。您必須獲取列表(只需瀏覽c:\ windows \ assembly)並將其過濾掉。你也可以考慮使用公司名稱(編輯我的答案)。 –

+0

在我的解決方案中,我確保所有類型都在我自己的命名空間層次結構中聲明。由於它們都具有相同的根名稱空間,我只需檢查方法的聲明類型的全名'frame.GetMethod()。DeclaringType.FullName'。如果它匹配'... FullName.StartsWith('MyRootNameSpace')',這是我的代碼,否則它是微軟或某個第三方的代碼。 – Zarepheth

4

如果您部署'* .pdb'文件,並且您只是試圖從異常中獲取堆棧跟蹤,則可以使用例外的StackTrace屬性並將其拆分成行並過濾掉沒有源的行代碼參考。

 catch (Exception ex) 
     { 
      var lines = ex.StackTrace 
       .Split(new[] {Environment.NewLine}, StringSplitOptions.None) 
       .Where(l => Regex.IsMatch(l, @"([^\)]*\)) in (.*):line (\d)*$")); 
      var userStackTrace = string.Join(Environment.NewLine, lines); 
     } 
+0

也是一種可行的方法,謝謝。 – NeverStopLearning

+0

我的+1,很好的主意,即使在PDB在那裏的調試階段的生產中也是如此。 –

0

我遇到了同樣的問題,但我使用了NLog和TraceSource並將System.Net Trace事件重定向到NLog目標。這就是說,篩選出系統組件並沒有完全切斷,所以我不得不檢查自定義屬性:

private static bool IsOkay(StackFrame arg) 
    { 
     var method = arg.GetMethod(); 
     var methodAttributes = new Attribute[] { } 
      .Concat(method.GetCustomAttributes<DebuggerHiddenAttribute>()) 
      .Concat(method.GetCustomAttributes<CompilerGeneratedAttribute>()); 

     if (methodAttributes.Any()) 
      return false; 

     var methodDeclearingType = method.DeclaringType; 
     var methodDeclearingTypeAttributes = new Attribute[] { } 
      .Concat(methodDeclearingType.GetCustomAttributes<CompilerGeneratedAttribute>()); 

     if (methodDeclearingTypeAttributes.Any()) 
      return false; 

     var methodDeclearingTypeModule = methodDeclearingType.Module; 
     var methodDeclearingTypeModuleAttributes = new Attribute[] { } 
      .Concat(methodDeclearingTypeModule.GetCustomAttributes<UnverifiableCodeAttribute>()); 

     if (methodDeclearingTypeModuleAttributes.Any()) 
      return false; 

     return true; 
    } 

BR, incureforce