. Los mensajes de rastreo .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 significa remark que este comportamiento es por diseño. El motivo por el que los mensajes se transmitieron 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 funcionó cuando se adjuntó un depurador nativo.
Una solución podría ser agregar un TraceListener
que reenvía todos los mensajes a otro proceso que no tiene un depurador conectado. La comunicación podría realizarse utilizando cualquier mecanismo de IPC. La siguiente es una muestra que usa sockets TCP.
Application Server
Esto sería un simple programa de línea de comandos independiente que se inicia y se 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");
}
}
De hecho cierto.Sin embargo, encontrará los mensajes de seguimiento en la ventana * Output * de Visual Studio. –
El problema se informó a MS: https://connect.microsoft.com/VisualStudio/feedback/details/457063/outputdebugstring-doesnt-work-in-the-debugger-vs-2010-pro-beta-1-c? wa = wsignin1.0 # y su respuesta fue que esto es "Por diseño". Si existe una solución alternativa, me encantaría saberlo. . . –
Soy consciente de que puedo usar la salida de Visual Studio. Pero no es tan útil como DebugView. Sin filtros, la maldita cosa sigue desplazándose ... Estoy sorprendido, como una gran herramienta como DebugView, de que no parece haber ninguna solución disponible. –