2010-12-13 6 views
27

SysInternals DebugView funktioniert nicht mehr, wenn es unter .NET 4 verwendet wird. Einige Forschungsergebnisse zeigten, dass die neue Architektur des Frameworks die Erfassung von Traces nicht zuließ, wenn ein Debugger angehängt wurde. In meinem Fall ist es der Visual Studio Debugger. Wenn Sie das Zielframework von 4 auf 3.5 ändern, funktioniert es wieder.Wie funktioniert DebugView unter .NET 4?

Jeder weiß eine Möglichkeit, DebugView unter .NET 4 zu arbeiten, während der Visual Studio Debugger angeschlossen ist? Ich habe versucht, die Listeners-Sammlung der Trace-Klasse zu löschen, aber kein Glück.

+2

In der Tat wahr.Sie finden jedoch die Ablaufverfolgungsmeldungen im Visual Studio-Fenster * Output *. –

+3

Das Problem wurde an MS gemeldet: https://connect.microsoft.com/VisualStudio/feedback/details/457063/outputdebugstring-doesnt-work-in-the-debugger-vs-2010-pro-beta-1-c? wa = wsignin1.0 # und ihre Antwort war, dass dies "By Design" ist. Wenn ein Workaround existiert, werde ich es gerne wissen. . . –

+0

Ich bin mir bewusst, dass ich die Ausgabe von Visual Studio verwenden kann. Aber es ist nicht annähernd so nützlich wie DebugView. Keine Filterung, das verdammte Ding scrollt einfach weiter ... Ich bin erstaunt, als großartiges Werkzeug wie DebugView ist, dass kein Workaround verfügbar zu sein scheint. –

Antwort

23

.NET Trace-Nachrichten werden mit der OutputDebugString-Funktion im Windows-Kernel ausgegeben. Diese Funktion sendet, wie in MSDN,

dokumentiert, eine Zeichenfolge an den Debugger zur Anzeige.

Offensichtlich wird ein nativer Debugger diese Nachricht erhalten. Dies ist mit der remark gemeint, dass dieses Verhalten von Entwurf ist. Der Grund, aus dem die Nachrichten an andere Listener wie DebugView vor .NET 4.0 weitergegeben wurden, ist, dass Visual Studio den .NET-Code nicht als "nativen" Debugger debuggte. DebugView hat nie funktioniert, wenn ein nativer Debugger angeschlossen ist.

Eine Problemumgehung könnte sein, eine TraceListener hinzuzufügen, die alle Nachrichten an einen anderen Prozess weiterleitet, der über keinen Debugger verfügt. Die Kommunikation könnte unter Verwendung irgendeines IPC-Mechanismus realisiert werden. Das folgende Beispiel zeigt TCP-Sockets.


Server Application

Dies würde ein einfaches Stand-alone-Kommandozeilen-Programm, das und automatisch gestoppt durch die TraceListener Klasse gestartet wird:

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); 
    } 
} 

Nutzungs

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

Danke. Große Erklärung und Workaround. –

+0

Das ist cool. Ich wünschte, ich könnte es zweimal aufwerten. Ich habe eine kleine Optimierung vorgenommen, die all das überspringt, wenn Sie nicht im Debugger laufen und DbgView ausführen. Wickeln Sie einfach den Initialisierungscode in etwas wie: if (Debugger.IsAttached && Process.GetProcessesByName ("Dbgview"). Any()) –

17

Je nach Bedarf gibt es eine einfachere Lösung: einfach Ihre Anwendung mit Strg-F5 ohne den Debugger starten.

Ich hatte gehofft, DebugView zu verwenden, um Debug-Anweisungen von einer gehosteten Silverlight-App zu erfassen, die im Debugger nicht funktioniert. Obwohl dies nicht wie vor .NET 4 funktioniert, lassen Sie die Debugger-Anweisungen durch den Start meines Hosts ohne Debugging durch und sie werden in DebugView angezeigt.

+1

Danke! Dies ist die einfachste Problemumgehung. – duyn9uyen

6

Diese feste, das Problem für mich:

Trace.Autoflush = true; 
+0

Groß- und Kleinschreibung: Trace.AutoFlush = true; –

2

ich in dieses Problem lief, als ich von .NET 4.5 einige Projekte herabgestuft auf .NET 4 - plötzlich alle meine Debug-View-Daten verschwunden (und ich war direkt PInvoking zu :: OutputDebugString). Wie auch immer, das Upgrade auf die neueste Version von Debug View (4.81) hat das Problem gelöst.