sysinternal password desktops .net debugging .net-4.0 tracing debugview

.net - desktops - sysinternals password



¿Cómo hacer que DebugView funcione bajo.NET 4? (4)

SysInternals ''DebugView ya no funciona si se usa en .NET 4. Algunas investigaciones indicaron que la nueva arquitectura del marco no permitía capturar rastros si se adjuntaba un depurador; En mi caso es el depurador de Visual Studio. Cambiar el marco de destino de 4 a 3.5 lo hace funcionar de nuevo.

¿Alguien conoce una forma de hacer que DebugView funcione bajo .NET 4 mientras se adjunta el depurador de Visual Studio? Intenté borrar la colección de Oyentes de la clase Trace, pero no tuve suerte.


Dependiendo de sus necesidades, hay una solución más sencilla: simplemente inicie su aplicación sin el depurador utilizando Ctrl-F5.

Esperaba usar DebugView para capturar sentencias de depuración de una aplicación de Silverlight alojada que no funciona en el depurador. Aunque esto no funciona como lo hizo antes de .NET 4, el lanzamiento de mi host sin depuración permite que pasen las declaraciones del depurador y se muestren en DebugView.


Esto solucionó el problema para mí:

Trace.Autoflush = true;


Me encontré con este problema cuando actualicé algunos proyectos de .NET 4.5 a .NET 4; de repente, todos mis datos de Debug View desaparecieron (y fui PInvoking directamente a :: OutputDebugString). De todos modos, la actualización a la última versión disponible de Debug View (4.81) solucionó el problema.


Los mensajes de rastreo de .NET se emiten utilizando la función OutputDebugString en el kernel de Windows. Esta función, como se documenta en MSDN,

envía una cadena al depurador para su visualización.

Obviamente, un depurador nativo recibirá este mensaje. Esto se entiende por la connect.microsoft.com/VisualStudio/feedback/details/457063/… que este comportamiento es por diseño. La razón por la que los mensajes se pasaron a otros oyentes como DebugView antes de .NET 4.0 es que Visual Studio no depuró el código .NET como un depurador "nativo"; DebugView nunca ha funcionado cuando se adjunta un depurador nativo.

Una solución alternativa podría ser agregar un TraceListener que TraceListener todos los mensajes a otro proceso que no tenga un depurador adjunto. La comunicación podría realizarse utilizando cualquier mecanismo de IPC. La siguiente es una muestra usando sockets TCP.

Aplicación de servidor

Este sería un programa de línea de comandos simple e independiente que se inicia y detiene automáticamente por la clase 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); } }

Uso

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