How to make DebugView work under .NET 4?
如果在.NET 4下使用,SysInternals的DebugView将不再起作用。一些研究表明,如果连接了调试器,该框架的新体系结构将无法捕获跟踪。 就我而言,它是Visual Studio调试器。 将目标框架从4更改为3.5使其可以再次工作。
有人知道在连接Visual Studio调试器的同时让DebugView在.NET 4下工作的方法吗? 我尝试清除Trace类的Listeners集合,但是没有运气。
使用Windows内核中的
sends a string to the debugger for display.
显然,本机调试器将收到此消息。这表示此行为是设计使然。消息在.NET 4.0之前传递给其他侦听器(如DebugView)的原因是Visual Studio并未将.NET代码作为"本机"调试器进行调试。连接本机调试器时,DebugView从未运行。
一种解决方法是添加
服务器应用
这将是一个简单的独立命令行程序,由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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(); } } } |
跟踪监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 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); } } |
用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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"); } } |
根据您的需求,有一个更简单的解决方法:使用Ctrl-F5无需调试器即可启动您的应用程序。
我曾希望使用DebugView从无法在调试器中运行的托管Silverlight应用程序捕获调试语句。尽管这与.NET 4之前的工作不同,但在未调试的情况下启动主机确实会使调试器语句通过,并且它们显示在DebugView中。
这为我解决了问题:
1 | Trace.AutoFlush = true; |
当我将某些项目从.NET 4.5降级到.NET 4时,我遇到了这个问题-突然我的所有Debug View数据都消失了(而我直接P调用了:: OutputDebugString)。无论如何,升级到最新的最新可用版本的Debug View(4.81)解决了该问题。