C# OutputDebugString/System.Diagnostics.Debug.WriteLine和Debugger.IsAttached

C# OutputDebugString/System.Diagnostics.Debug.WriteLine和Debugger.IsAttached,c#,C#,我需要检查OutputDebugString/System.Diagnostics.Debug.WriteLine的输出是否将转到never-land 似乎OutputDebugString是System.Diagnostics.Debug.WriteLine写入内部跟踪侦听器时的本机方法 Debugger.IsAttached是否对此进行了足够的检查 如果运行类似于DebugView的程序,则Debugger.IsAttached似乎无法启动。我需要能够检查是否有任何东西可以看到OutputD

我需要检查OutputDebugString/System.Diagnostics.Debug.WriteLine的输出是否将转到never-land

似乎OutputDebugString是System.Diagnostics.Debug.WriteLine写入内部跟踪侦听器时的本机方法

Debugger.IsAttached是否对此进行了足够的检查


如果运行类似于DebugView的程序,则Debugger.IsAttached似乎无法启动。我需要能够检查是否有任何东西可以看到OutputDebugString/System.Diagnostics.Debug.WriteLine的输出。

如果您愿意弄脏您的手并使用一些本地的东西,您可以实现这一点。您需要使用P/Invoke

可以看出,
OutputDebugString
基于4个内核对象
Mutex
命名为
DBWinMutex
,一个共享内存
DBWIN\u BUFFER
和两个事件(
DBWIN\u BUFFER\u READY
DBWIN\u DATA\u READY
),正如他们在文章中所写的那样-我们不能依赖Mutex,因为它一直存在。但是我们可以检查是否创建了共享部分

如果我们从pinvoke.net导入到我们的项目中

static class NativeFunctions
{
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr OpenFileMapping(
        uint dwDesiredAccess, 
        bool bInheritHandle,
        string lpName);
}
然后我们可以检查是否创建了该部分,并根据该部分判断是否有内容正在侦听

编写这个简单的程序

public const int FILE_MAP_READ = 0x0004;
static void Main(string[] args)
{
    if (NativeFunctions.OpenFileMapping(FILE_MAP_READ, false, "DBWIN_BUFFER") != IntPtr.Zero)
    {
        Log("Someone is listening");
    }
    else
    {
        Log("I am here alone");
    }
}

private static void Log(string log)
{
    Debug.WriteLine(log);
    Console.WriteLine(log);
}
当我们不跑步时,我们会听到“我一个人在这里”

用这个工具呢


此外,还需要澄清以下内容:“.while System.Diagnostics.Debug.WriteLine正在写入内部跟踪侦听器。”
Debug.WriteLine
也将写入与
OutputDebugString
相同的位置,但前提是VS未连接-否则VS将捕获日志并发布到其输出窗口。

请问您为什么需要检查此项?您的情况如何?如果未连接调试器,则不生成输出会带来性能提升?这有点超出了
OutputDebugString
的权限。对于跟踪侦听器,如果没有人关心,您可以使用
TraceSwitch
来阻止生成任何内容。@jeroenmoster——没错。在我的应用程序中生成诊断信息可能“昂贵”。如果没有任何内容正在侦听输出,我希望跳过生成它。我不想使用app.config或注册表项。我想基于内部bool实现最高性能。我也不想依赖TraceSwitch,因为它需要app.config的东西,这是一个共享库。。。我想自动处理。@Amy,更多信息,请参阅我对Jeroen的回答。你对“稍后”的人感兴趣吗?不生成信息的最快方法是检查
静态只读bool
,因为JIT将能够在运行时优化整个代码,其显著缺点是在应用程序运行时无法重新打开日志记录。非常酷的Pawel!我必须测试性能:),执行isDebuggerAttached和此检查可能比运行实际代码更昂贵:),但它确实检测到debugview.Hmm。。不幸的是,这张支票很贵。100k检查为1100ms,而调试器仅为10ms。附加:(…我读了你链接的文章,有另一种想法,我正在尝试…观察DBWIN_BUFFER_READY事件并等待它发出信号。这样它将是一个阻塞事件…可能是这样的。PInvoke在.NET上速度很慢。请记住,
Debugger.IsAttached
只有在附加了调试器时才是真的,并且它不会检测到DebugView。使用您的任务所需的内容。我很乐意研究这个主题,甚至扩展我的知识。我想唯一的解决方案是等待DBWIN_BUFFER_准备好发出信号(侦听器启动),然后在DBWIN_BUFFER上循环等待并短暂睡眠(侦听器停止).Shugh。在侦听器停止之前,我找不到任何其他方法来阻止。您正在泄漏句柄。每个
OpenFileMapping
都会保留一个打开的句柄。每次检查都会消耗一大块进程的分页池。此外,如果不关闭句柄,即使WinDbg关闭,映射也会保留!您必须调用::CloseHandle()如果调用成功。@SledgeHammer,你是对的,打开文件映射不是一个便宜的操作。文章说,在侦听器连接之前不会创建事件,你可以使用这个事实。打开事件要快得多(不是快,只是快得多)。当然,你知道整个过程是一个巨大的未记录的黑客行为。