2010-12-13 55 views
27

如果在.NET 4下使用,SysInternals的DebugView不再有效。一些研究表明,如果连接了调试器,则框架的新架构不允许捕获跟踪;在我的情况下,它是Visual Studio调试器。将目标框架从4更改为3.5使其再次运行。如何让DebugView在.NET 4下工作?

任何人都知道在Visual Studio调试器连接的情况下让DebugView在.NET 4下工作的方法吗?我尝试清除Trace类的Listeners集合,但没有运气。

+2

的确如此。但是,您会在Visual Studio的* Output *窗口中找到跟踪消息。 – 2010-12-13 13:39:52

+3

该问题已报告给MS:https://connect.microsoft.com/VisualStudio/feedback/details/457063/outputdebugstring-doesnt-work-in-the-debugger-vs-2010-pro-beta-1-c? wa = wsignin1.0#,他们的回答是这是“By Design”。如果解决方法存在,我很乐意知道它。 。 。 – 2010-12-13 13:42:27

+0

我知道我可以使用Visual Studio的输出。但它不如DebugView那么有用。没有过滤,该死的东西只是保持滚动......我很惊讶,作为DebugView的工具,没有解决方法似乎可用。 – 2010-12-13 15:53:27

回答

23

.NET跟踪消息使用Windows内核中的OutputDebugString函数发出。此功能,如MSDN中记录的,

将字符串发送到调试器进行显示。

显然,本地调试器会收到此消息。这是由remark这个行为是有意设计的。在.NET 4.0之前将消息传递给其他监听器(如DebugView)的原因是Visual Studio没有将.NET代码作为“本机”调试器进行调试;当连接本机调试器时,DebugView从未工作。

解决方法可能是添加一个TraceListener,将所有消息转发到没有附加调试器的另一个进程。通信可以使用任何IPC机制来实现。以下是使用TCP套接字的示例。


服务器应用

这将是被启动,并且由TraceListener类自动停止一个简单独立的命令行程序:

using System; 
using System.Diagnostics; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     if (args.Length != 1) 
     { 
      Console.WriteLine("Usage: DebugOutputListener.exe <port>"); 
      return; 
     } 
     TcpListener server = null; 
     try 
     { 
      Int32 port = Convert.ToInt32(args[0]); 
      IPAddress localAddr = IPAddress.Parse("127.0.0.1"); 

      server = new TcpListener(localAddr, port); 
      server.Start(); 

      while (true) 
      { 
       Console.Write("Waiting for a connection... "); 

       using (TcpClient client = server.AcceptTcpClient()) 
       { 
        using (NetworkStream stream = client.GetStream()) 
        { 

         byte[] bufferLength = new byte[4]; 
         stream.Read(bufferLength, 0, 4); 
         int length = BitConverter.ToInt32(bufferLength, 0); 

         if (length == -1) 
         { 
          // close message received 
          Trace.WriteLine("DebugOutputListener is closing."); 
          return; 
         } 

         byte[] bufferMessage = new byte[length]; 
         stream.Read(bufferMessage, 0, length); 

         string msg = Encoding.UTF8.GetString(bufferMessage); 
         Trace.WriteLine(msg); 
        } 
       } 
      } 
     } 
     catch (SocketException e) 
     { 
      Console.WriteLine("SocketException: {0}", e); 
     } 
     finally 
     { 
      server.Stop(); 
     } 
    } 
} 

的TraceListener

using System; 
using System.Diagnostics; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 

public class DebugOutputTraceListener : TraceListener 
{ 
    private IPEndPoint ipEndPoint; 
    private bool needsDisposing; 

    public DebugOutputTraceListener(string debugOutputListenerPath, int port) 
    { 
     this.ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000); 

     // start the process that forwards the trace messages 
     var psi = new ProcessStartInfo() 
     { 
      FileName = debugOutputListenerPath, 
      Arguments = port.ToString(), 
      CreateNoWindow = true, 
      UseShellExecute = false 
     }; 
     Process.Start(psi); 
     needsDisposing = true; 
    } 

    ~DebugOutputTraceListener() 
    { 
     Dispose(false); 
    } 

    public override void Write(string message) 
    { 
     sendMessage(message); 
    } 

    public override void WriteLine(string message) 
    { 
     sendMessage(message + Environment.NewLine); 
    } 

    private void sendMessage(string message) 
    { 
     try 
     { 
      using (TcpClient client = new TcpClient()) 
      { 
       client.Connect(ipEndPoint); 
       byte[] bufferMessage = Encoding.UTF8.GetBytes(message); 
       byte[] bufferLength = 
        BitConverter.GetBytes(bufferMessage.Length); 

       using (NetworkStream stream = client.GetStream()) 
       { 
        stream.Write(bufferLength, 0, bufferLength.Length); 
        stream.Write(bufferMessage, 0, bufferMessage.Length); 
       } 
      } 
     } 
     catch (SocketException e) 
     { 
      Trace.WriteLine(e.ToString()); 
     } 
    } 

    /// <summary> 
    /// Sends -1 to close the TCP listener server. 
    /// </summary> 
    private void sendCloseMessage() 
    { 
     try 
     { 
      using (TcpClient client = new TcpClient()) 
      { 
       client.Connect(ipEndPoint); 
       byte[] buffer = BitConverter.GetBytes(-1); 

       using (NetworkStream stream = client.GetStream()) 
       { 
        stream.Write(buffer, 0, buffer.Length); 
       } 
      } 
     } 
     catch (SocketException e) 
     { 
      Trace.WriteLine(e.ToString()); 
     } 
    } 

    public override void Close() 
    { 
     sendCloseMessage(); 
     needsDisposing = false; 
     base.Close(); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (needsDisposing) 
     { 
      sendCloseMessage(); 
      needsDisposing = false; 
     } 
     base.Dispose(disposing); 
    } 
} 

使用

public class Program 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     // using Debug; start a listener process on port 13000 
     Debug.Listeners.Add(
      new DebugOutputTraceListener("DebugOutputListener.exe", 13000)); 
     Debug.WriteLine("A debug message."); 

     // using Trace; start a listener process on port 13001 
     Trace.Listeners.Add(
      new DebugOutputTraceListener("DebugOutputListener.exe", 13001)); 
     Trace.WriteLine("A trace message"); 
    } 
} 
+0

谢谢。很好的解释和解决方法。 – 2010-12-14 13:40:12

+0

这很酷。希望我可以两次投票赞成。我做了一个小的优化,如果你没有在调试器中运行并运行DbgView,则跳过所有这些。只需将初始化代码包装为如下形式:if(Debugger.IsAttached && Process.GetProcessesByName(“Dbgview”)。Any()) – 2014-08-15 20:40:29

17

根据您的需求,还有一个更简单的解决方法:刚开始你的应用,而无需通过使用Ctrl-F5调试器。

我曾希望使用DebugView从托管的Silverlight应用程序捕获调试语句,该应用程序在调试器中不起作用。虽然这不像.NET 4之前的那样工作,但是在没有调试的情况下启动主机会让调试器语句通过,并且它们会显示在DebugView中。

+1

谢谢!这是最简单的解决方法。 – duyn9uyen 2014-05-19 17:29:06

6

这个固定的问题对我来说:

Trace.Autoflush = true; 
+0

区分大小写:Trace.AutoFlush = true; – 2016-10-17 05:25:04

2

我就遇到了这个问题,当我从降级.NET 4.5的一些项目到.NET 4 - 突然我所有的调试视图数据消失(我直接PInvoking到:: OutputDebugString)。无论如何,升级到后期最新版本的Debug View(4.81)解决了这个问题。