2013-10-14 55 views
4

我使用第三方庫,這使得多次打電話給該函數:禁止跟蹤消息從特定DLL

Trace.WriteLine(string message); 

這雜波了Visual Studio的輸出窗口和調試,使我的申請困難(例如, XAML綁定警告)。

我試圖找到一種方法來停止從特定dll的所有跟蹤消息從轉儲到visual studio輸出窗口 - 正在寫我自己的TraceListener唯一的路徑向前?


我不能讓一個TraceFilter/EventTypeFilter的字符串信息工作沒有類別 - 雖然我不能找到文檔來支持這一行動 - 經驗:

TraceFilter.ShouldTrace(...) 

由以下功能(不是一個完整的組)稱爲:

Trace.WriteLine(string message, string category); 
Trace.TraceError(string message); 
Trace.WriteLine(object o); 

但不是C alled:

Trace.WriteLine(string message); 

有誰知道爲什麼這個調用避免了ShouldTrace過濾器?

+0

只是想知道,你爲什麼不希望讓自己的'TraceListener'? – jrh

+0

@jrh如果我沒有記錯,我試圖擺脫在Visual Studio輸出窗口中的所有這些額外的消息,所以我可以調試其他問題,如綁定問題。另外,在我使用的庫的未來版本中,作者刪除了他們的Trace.WriteLine調用 – sfm

+0

在這種情況下,我想我知道一個簡單的解決方案,我會在一週後發佈答案,當我得到背部。但是,您在自己的代碼中使用了Trace.WriteLine,對嗎?意思是說,你不只是想要壓制所有的Trace.WriteLine消息,只是來自一個dll的消息。 – jrh

回答

0

ILSpy,在Trace.WriteLine(string message)被聲明爲抽象的,需要由派生類中重寫:

public abstract void WriteLine(string message); 

你提到的所有其他方法檢查ShouldTrace最終調用Trace.WriteLine(string message)消息。

例如爲:

public virtual void WriteLine(string message, string category) 
{ 
    if (Filter != null && 
     !Filter.ShouldTrace(null, "", TraceEventType.Verbose, 0, message)) 
    { 
     return; 
    } 
    if (category == null) 
    { 
     WriteLine(message); 
     return; 
    } 
    WriteLine(category + ": " + ((message == null) ? string.Empty : message)); 
} 

所以,真正的原因是在我看來,在Trace類的設計者的決定。

他可以作出Trace.WriteLine(string message)保護,incidate它不打算直接調用,如:

protected abstract void WriteLine(string message); 
+2

我認爲這解釋了設計。如果第三方庫正在調用Trace.WriteLine(字符串消息),是否無法過濾和抑制這些消息? – sfm

+0

似乎沒有辦法繞過 – liuhongbo

0
  1. 如果你不想創建自己的TraceListener,唯一的方式來抑制來自有問題的dll的Trace消息是通過使用Trace.Listeners.Clear()來停止所有Trace消息。

請注意,這也會阻止您自己的Trace調用。我提到這一點是因爲我知道一些從未使用過的應用程序,並且在不斷寫入輸出窗口的非常嘈雜的庫中受到嚴重的性能影響。

  1. 我會建議創建一個TraceListener,它使用反射查找要在調用堆棧中忽略的dll。

無法覆蓋Trace.WriteLine,但可以覆蓋默認TraceListener中的某些呼叫以實現相同的效果。

使用如下所示的TraceListener可以幫助您清理Visual Studio中的輸出窗口,以便您可以專注於感興趣的事件,而不會受到來自第三方庫的消息的轟炸。

見下面的示例代碼:

using System; 
using System.Diagnostics; 
using System.Reflection; 

// The library that calls Trace, causing the messages you want to suppress. 
using NoisyLibrary; 

namespace TraceSuppress 
{ 
    /// <summary> 
    /// Trace listener that ignores trace messages from a specific assembly. 
    /// </summary> 
    public class AssemblyFilteredListener : DefaultTraceListener 
    { 
     private Assembly assemblyToIgnore; 

     public AssemblyFilteredListener(Assembly assemblyToIgnoreTracesFrom) 
     { 
      this.assemblyToIgnore = assemblyToIgnoreTracesFrom; 
     } 

     public bool TraceIsFromAssemblyToIgnore() 
     { 
      StackTrace traceCallStack = new StackTrace(); 

      StackFrame[] traceStackFrames = traceCallStack.GetFrames(); 

      // Look for the assembly to ignore in the call stack. 
      // 
      // This may be rather slow for very large call stacks. If you find that this is a bottleneck 
      // there are optimizations available. 
      foreach (StackFrame traceStackFrame in traceStackFrames) 
      { 
       MethodBase callStackMethod = traceStackFrame.GetMethod(); 

       bool methodIsFromAssemblyToIgnore = (callStackMethod.Module.Assembly == this.assemblyToIgnore); 

       if (methodIsFromAssemblyToIgnore) 
       { 
        return true; 
       } 

      } 

      // The assembly to ignore was not found in the call stack. 
      return false;   

     } 


     public override void WriteLine(string message) 
     { 
      if (!this.TraceIsFromAssemblyToIgnore()) 
      { 
       base.WriteLine(message); 
      } 
     }   

     public override void Write(string message) 
     { 
      if (!this.TraceIsFromAssemblyToIgnore()) 
      { 
       base.Write(message); 
      } 
     } 
    } 

    class Program 
    { 
     static void SetupListeners() 
     { 
      // Clear out the default trace listener 
      Trace.Listeners.Clear(); 

      // Grab the asssembly of the library, using any class from the library. 
      Assembly assemblyToIgnore = typeof(NoisyLibrary.LibraryClass).Assembly; 

      // Create a TraceListener that will ignore trace messages from that library 
      TraceListener thisApplicationOnlyListener = new AssemblyFilteredListener(assemblyToIgnore); 

      Trace.Listeners.Add(thisApplicationOnlyListener); 

      // Now the custom trace listener is the only listener in Trace.Listeners. 
     } 

     static void Main(string[] args) 
     { 
      SetupListeners();    

      // Testing 
      //------------------------------------------------------------------------- 

      // This still shows up in the output window in VS... 
      Trace.WriteLine("This is a trace from the application, we want to see this."); 

      // ...but the library function that calls trace no longer shows up. 
      LibraryClass.MethodThatCallsTrace(); 

      // Now check the output window, the trace calls from that library will not be present. 

     } 
    } 
} 
+0

如果有人感興趣,[這裏有一些測試代碼在顯示NoisyLibrary背後的源代碼](https://gist.github.com/anonymous/3f47814a0031524a2843d1214a0e7ac8)。 - 基本要點上的.cs語法突出顯示效果並不好,所以我將它設置爲cpp。 – jrh