如果在.NET 4下使用,SysInternals的DebugView不再有效。一些研究表明,如果连接了调试器,则框架的新架构不允许捕获跟踪;在我的情况下,它是Visual Studio调试器。将目标框架从4更改为3.5使其再次运行。如何让DebugView在.NET 4下工作?
任何人都知道在Visual Studio调试器连接的情况下让DebugView在.NET 4下工作的方法吗?我尝试清除Trace类的Listeners集合,但没有运气。
如果在.NET 4下使用,SysInternals的DebugView不再有效。一些研究表明,如果连接了调试器,则框架的新架构不允许捕获跟踪;在我的情况下,它是Visual Studio调试器。将目标框架从4更改为3.5使其再次运行。如何让DebugView在.NET 4下工作?
任何人都知道在Visual Studio调试器连接的情况下让DebugView在.NET 4下工作的方法吗?我尝试清除Trace类的Listeners集合,但没有运气。
.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");
}
}
谢谢。很好的解释和解决方法。 – 2010-12-14 13:40:12
这很酷。希望我可以两次投票赞成。我做了一个小的优化,如果你没有在调试器中运行并运行DbgView,则跳过所有这些。只需将初始化代码包装为如下形式:if(Debugger.IsAttached && Process.GetProcessesByName(“Dbgview”)。Any()) – 2014-08-15 20:40:29
根据您的需求,还有一个更简单的解决方法:刚开始你的应用,而无需通过使用Ctrl-F5调试器。
我曾希望使用DebugView从托管的Silverlight应用程序捕获调试语句,该应用程序在调试器中不起作用。虽然这不像.NET 4之前的那样工作,但是在没有调试的情况下启动主机会让调试器语句通过,并且它们会显示在DebugView中。
谢谢!这是最简单的解决方法。 – duyn9uyen 2014-05-19 17:29:06
这个固定的问题对我来说:
Trace.Autoflush = true;
区分大小写:Trace.AutoFlush = true; – 2016-10-17 05:25:04
我就遇到了这个问题,当我从降级.NET 4.5的一些项目到.NET 4 - 突然我所有的调试视图数据消失(我直接PInvoking到:: OutputDebugString)。无论如何,升级到后期最新版本的Debug View(4.81)解决了这个问题。
的确如此。但是,您会在Visual Studio的* Output *窗口中找到跟踪消息。 – 2010-12-13 13:39:52
该问题已报告给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
我知道我可以使用Visual Studio的输出。但它不如DebugView那么有用。没有过滤,该死的东西只是保持滚动......我很惊讶,作为DebugView的工具,没有解决方法似乎可用。 – 2010-12-13 15:53:27