Is it possible to suppress the verbose debug output from a third-party DLL? My debug output window is flooded with them. I can't modify the DLL in question.
问题:
回答1:
I don't think that there are any simple way to do this.
One way will work in any way is API-hooking (or function hooking). There are different way how one can do this.
If the DLL where you want to deny debug output import OutputDebugString
function directly (use dumpbin /imports thedll.dll
) one can patch PE import address table (IMAGE_THUNK_DATA
) of the DLL in memory to point the reference to your dummy function which do nothing.
If you don't know exactly which API are used by the third-party DLL you can use code overwriting technique so that the code of OutputDebugString
function in the memory of your process will be changed (JMP or CALL instruction) so that your function will be called, your code can examine the call stack and if the third-party DLL are inside you can do nothing. In case that you don't find the third-party DLL on the call stack you can forward the call to original implementation of OutputDebugString
.
Both of the describes techniques are used in DLL-Injection. In your case you have more easy case because you need to do the changes in your own process, so no special user rights are required.
All the described technique are not simple like I wrote at the beginning of my answer. I wrote at the beginning of my answer that I don't think that any simple way exist. On the other side you don't need to implement all which described above yourself. You can find enough code example in the internet in many computer languages.
回答2:
I don't think so, because a debug output trace record has no owner.
If the rogue traces exhibit some patterns, you can filter them out using an open source tool similar to DebugView I wrote for this kind of problem: TraceSpy, but in this case, you'll need to visualize the traces outside of Visual Studio. It won't change the OutputWindow behavior.
回答3:
There is a very simple way to achieve this, contact the original developer and ask them to supply you a dll built as Release instead of Debug. Just flipping that switch will turn off all of the messages as the Debug.Xxxx() methods all get optimised away under a release compilation for each assembly.
回答4:
I don't know if you can conditionally filter messages in a straight forward way.
But you can call System.Diagnostics.Debug.Listeners.Clear() as your first statement in the main(), which will basically don't print anything at all for the running session.
回答5:
If you are debugging with WinDbg (which offers many more possibilities than the VS debugger) you can use the ".ofilter" command to suppress specific messages or possibly event filters to suppress all messages emitted by a module. If you really want to use visual studio you can (in version 2010 at least) directly issue WinDbg commands in the "Immediate Window" though I'm not sure if the .ofilter command is available - I tried it quickly here and it didn't work but maybe it's worth a try.
回答6:
What if you filter inside the traceListener?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Debug.WriteLine("Hello world");
Debug.Listeners.Clear();
var listener = new FilteringListener();
listener.IgnoredAssemblies.Add("ConsoleApplication1");
Debug.Listeners.Add(listener);
Debug.WriteLine("Goodbye");
Console.Read();
}
}
}
namespace ConsoleApplication1
{
public class FilteringListener : System.Diagnostics.TraceListener
{
public FilteringListener()
{
IgnoredAssemblies = new List<string>();
_inner = new DefaultTraceListener();
}
private DefaultTraceListener _inner;
public List<String> IgnoredAssemblies { get; private set; }
public override void Write(string message)
{
if (ShouldFilter())
_inner.Write(message);
}
private bool ShouldFilter()
{
var stack = new StackTrace();
var stackFrame = stack.GetFrame(4);
var method = stackFrame.GetMethod();
var assembly = method.DeclaringType.Assembly;
return !IgnoredAssemblies.Any(x => assembly.FullName.Contains(x);
}
public override void WriteLine(string message)
{
if (ShouldFilter())
_inner.WriteLine(message);
}
}
}
Of course the problem with this implementation is requires that the inner workings calling the new Listener don't change, so the stack offset of 4 remains valid. But since this is only for your debug output, at least you introduce a production bug, just bad trace output again.