我的程序如何监听OutputDebugString输出并允许启动多个实例?

3
这里是我的场景:我有一个程序,它使用OutputDebugString()产生调试输出,其中可能包含指示错误的消息。我想在日常构建中运行此程序,并自动侦听调试输出、解析它并报告可疑输出。
有几个这样的监听器实现示例,例如这个。它们都做同样的事情——监听系统范围内的事件,然后从文件映射中读取数据。问题是,该协议仅允许一个监听器实例 - 谁先获取到事件就是唯一可以访问输出的人。
DebugView程序也是如此。如果我有一个正在运行的实例,那么启动另一个实例将产生一个“断开连接”的实例,它将无法“连接到本地”。
日常构建同时运行多个程序,因此我希望能够运行多个此监听器实例,并且每个实例仅侦听特定程序。看起来Visual Studio可以做到这一点——当我在Visual Studio下启动一个程序时,我只会看到该程序的调试输出,而不是其他程序的输出。我还可以运行多个Visual Studio实例,并在同一时间内调试每个程序。
是否可能运行与DebugView相当的几个程序实例,以便每个实例仅侦听特定的被观察程序,并且实例之间不会相互干扰?

看起来像是Visual Studio可以做到这一点 - 你弄错了。调试器通过DBG_PRINTEXCEPTION_CDBG_PRINTEXCEPTION_WIDE_C异常接收通知。能否运行多个实例?- 不可能的,只存在一个部分、事件等,所以会出现数据竞争。 - undefined
你可以编写一个调试器,在其下运行你的应用程序,并像VS一样获得通知。这并不是一件简单的事情,但也不是什么难以理解的高深技术。 - undefined
一个实例可以捕获多个程序的调试输出,你可以通过进程ID来区分它们。所以一个就足够了吗? - undefined
对于每个感兴趣的程序,启动一个监听器实例会更加方便。 - undefined
1
@500-服务器内部错误。谢谢。我按照你的提示操作,比我预期的要简单得多。我写了一个摘要作为答案。 - undefined
1个回答

3
我按照用户500 - Internal Server Error在评论中给出的提示,尝试了“假装 Visual Studio”的方法。这种方法难度非常高(但我有10多年的WinAPI软件开发经验),整个过程花费了几个小时,实现不到200行C++代码,其中包括一些用于调用WinAPI函数和过滤输出并以可用方式报告可疑项的笨重代码。
有趣的是,我使用Visual Studio编写和调试代码——Visual Studio作为正在开发的程序的调试器,而正在开发的程序又作为正在产生奇怪调试输出的程序的调试器,这个链条运行良好。
以下是一个很好的教程,可以获得灵感:编写基本的Windows调试器,这是一个MSDN关于如何编写调试器主循环的解释:编写调试器的主循环
它的工作原理如下:
  1. 使用CreateProcess()启动要处理调试输出的程序,并传递DEBUG_ONLY_THIS_PROCESS标志。这会暂停程序并在“被调试”模式下启动程序。
  2. 运行一个无限循环,并在每次迭代上调用WaitForDebugEvent()。调用WaitForDebugEvent()会恢复暂停的程序,并允许它运行,直到发生下一个调试事件。
  3. 处理OUTPUT_DEBUG_STRING_EVENT,使用ReadProcessMemory()从被调试的进程中复制字符串,根据需要处理字符串。
  4. 还要处理EXIT_PROCESS_DEBUG_EVENT——这意味着正在调试的进程已退出,并且您可能想要结束循环。
  5. 还要处理EXCEPTION_DEBUG_EVENT——当EXCEPTION_DEBUG_INFO.dwFirstChance为零时,必须使用TerminateProcess()终止正在调试的进程,否则您将得到一个不方便的“程序已停止工作”的对话框。
  6. 在循环迭代结束时调用ContinueDebugEvent(),传递DBG_EXCEPTION_NOT_HANDLED
就是这样。是的,现在你可以声称自己有编写调试器的经验了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接