禁止显示来自特定 DLL 的跟踪消息
本文关键字:跟踪 消息 DLL 禁止显示 | 更新日期: 2023-09-27 18:35:24
我正在使用一个第三方库,它对该函数进行了多次调用:
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);
但未被以下人员调用:
Trace.WriteLine(string message);
有谁知道为什么这个调用避免了ShouldTrace过滤器?
- 如果您不想创建自己的
TraceListener
,则禁止来自有问题的 dll 的Trace
消息的唯一方法是使用Trace.Listeners.Clear()
停止所有Trace
消息。
请注意,这也将停止您自己的Trace
调用。我之所以提到这一点,是因为我知道一些应用程序从未使用过Trace.WriteLine
并且由于不断写入输出窗口的非常嘈杂的库而受到严重的性能影响。
- 我建议创建一个使用反射在调用堆栈中查找要忽略的 dll 的
TraceListener
。
覆盖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.
}
}
}
根据 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)
,以表明它不打算直接调用,例如:
protected abstract void WriteLine(string message);