使用 DML 自定义调试器输出

调试器标记语言 (DML) 提供了一种机制来增强调试器和扩展的输出。 与 HTML 类似,调试器的标记支持允许输出以标记的形式包含显示指令和额外的非显示信息。 调试器用户界面(如 WinDbg)会解析 DML 中提供的额外信息,以增强信息的显示并提供新行为,例如网格显示和排序。 本主题介绍如何使用 DML 自定义调试输出。 有关在调试器中启用和使用 DML 的一般信息,请参阅 使用调试器标记语言

DML 在 Windows 10 及更高版本中可用。

DML 概述

DML 的主要优势是提供链接到调试器输出中相关信息的功能。 主要 DML 标记之一是 <链接> 标记,它允许输出生成者指示可以通过链接的所述操作访问与输出片段相关的信息。 与 Web 浏览器中的 HTML 链接一样,这允许用户导航超链接信息。

提供超链接内容的好处是,它可用于增强调试器和调试器扩展功能的可发现性。 调试器及其扩展包含大量功能,但可能很难确定用于不同方案的相应命令。 用户必须仅知道哪些命令可用于特定方案。 用户和内核调试之间的差异进一步增加了复杂性。 这通常意味着许多用户不知道可以帮助他们的调试命令。 DML 链接使任意调试命令能够包装在备用演示文稿中,例如描述性文本、可单击的菜单系统或链接的帮助。 使用 DML,可以增强命令输出,以引导用户获取与手头任务相关的其他相关命令。

调试器 DML 支持

  • WinDbg 中的命令窗口支持所有 DML 行为,并显示颜色、字体样式和链接。
  • 控制台调试器 (ntsd、cdb 和 kd) 仅支持 DML 的颜色属性,仅在启用了颜色模式的真正控制台中运行时,才支持 。
  • 具有重定向 I/O、ntsd –d 或 remote.exe 会话的调试器不会显示任何颜色。

DML 内容规范

DML 不是完整的呈现语言(如 HTML)。 DML 特意非常简单,只有几个标记。

由于并非所有调试器工具都支持格式文本,因此 DML 旨在允许在 DML 和纯文本之间进行简单翻译。 这允许 DML 在所有现有调试器工具中运行。 可以轻松支持颜色等效果,因为删除它们不会删除包含实际信息的文本。

DML 不是 XML。 DML 不会尝试携带语义或结构化信息。 如上所述,DML 和纯文本之间必须有一个简单的映射,因此,DML 标记都是可丢弃的。

DML 不可扩展;所有标记都已预定义并经过验证,可跨所有现有调试器工具运行。

标记结构

与 XML 类似,DML 标记以起始 <标记名 [args]> 和以下 </tagname> 的形式提供。

特殊字符

DML 内容大致遵循特殊字符的 XML/HTML 规则。 &、 <> 和 “的字符是特殊字符,不能在纯文本中使用。 等效的转义版本 &、 <> 和 ”。 例如,以下文本:

“爱丽丝 & 鲍勃想 3 < 4”

将转换为以下 DML。

"Alice & Bob think 3 &lt 4"

C 编程语言格式字符

与 XML/HTML 规则的显著区别在于,DML 文本可以包含 C 编程语言流样式格式字符,例如 \b、\t、\r 和 \n。 这是为了支持与现有调试器文本生产和使用的兼容性。

示例 DML

假设文件 C:\Dml_Experiment.txt 包含以下行。

My DML Experiment
<link cmd="lmD musb*">List modules that begin with usb.</link>

以下命令在“命令浏览器”窗口中显示文本和链接。

.browse .dml_start c:\Dml_Experiment.txt

命令浏览器窗口中 DML 文件输出的屏幕截图。

如果单击 以 usb 开头的“列出模块” 链接,将看到类似于下图的输出。

在 DML 输出中单击链接后模块列表的屏幕截图。

DML 中的右键单击行为

DML 中提供右键单击行为。 此示例演示如何使用 <altlink> 定义右键单击行为,以发送断点 bp (Set 断点) 命令,并通过定期单击发送 u (Unassemble)

<link cmd="u MyProgram!memcpy">
<altlink name="Set Breakpoint (bp)" cmd="bp MyProgram!memcpy" />
u MyProgram!memcpy
</link>

DML 标记参考

<link [name=“text”] [cmd=“debugger_command”][alt=“悬停显示文本”] [section=“name”]>链接文本</link>

链接标记是 DML 中的基本超链接机制。 它指示支持 DML 演示文稿的用户界面将链接文本显示为可单击的链接。 单击具有 cmd 规范的链接时,将执行调试器命令,其输出应替换当前输出。

名称和节参数允许在命名链接之间导航,类似于 HTML 的名称<>和 #name 支持。 在 UI 上单击具有 section 参数的链接时,将扫描名为 且名称匹配的链接,并将该链接滚动到视图中。 这允许链接指向同一页 (的不同部分或新页面) 的特定部分。 DML 的节名称是分开的,以避免必须定义允许在命令字符串末尾使用节名称的新语法。

转换为纯文本会删除标记。

示例

<b> Handy Links </b>
<link cmd="!dml_proc">Display process information with DML rendering.</link>
<link cmd="kM">Display stack information with DML rendering.</link>

示例

此示例演示如何使用 alt 属性创建将鼠标悬停在 DML 链接上时显示的文本。

<b>Hover Example</b>
<link cmd="lmD" alt="This link will run the list modules command and display the output in DML format">LmD</link>

<altlink [name=“text”] [cmd=“debugger_command”] [section=“name”]>alt link text</altlink>

<altlink> 标记提供右键单击行为,在 DML 中可用。 单击具有 cmd 规范的链接时,将执行调试器命令,其输出应替换当前输出。 <altlink> 选项卡通常与链接>标记配对,<以支持常规和右键单击行为。

转换为纯文本会删除标记。

示例

此示例演示如何使用 <altlink> 定义右键单击行为,以发送断点 bp (Set 断点) 命令,并使用常规单击发送 u (Unassemble)

<link cmd="u MyProgram!memcpy">
<altlink name="Set Breakpoint (bp)" cmd="bp MyProgram!memcpy" />
u MyProgram!memcpy
</link>

<Exec>

<exec cmd=“debugger_command”>描述性文本</exec>

exec 标记类似于链接标记,因为描述性文本应显示为可单击的项。 但是,在命令浏览器窗口中使用 exec 标记时,执行给定命令而不替换当前输出,此标记提供了一种通过单击从菜单执行命令的方法。

转换为纯文本会删除标记。

示例

此示例演示如何使用常规单击定义两个命令。

<b>Exec Sample</b>
<exec cmd="!dml_proc">Display process information with DML rendering.</exec>
<exec cmd="kM">Display stack information with DML rendering.</exec>

<B>

<b>粗体文本</b>

此标记请求加粗。 <b>、<i> 和 <u> 可以嵌套为混合属性。

转换为纯文本会删除标记。

示例

此示例演示如何加粗文本。

<b>This is bold Text</b>

<我>

<i>斜体文本</i>

此标记请求斜体。 <b>、<i> 和 <u> 可以嵌套为混合属性。

转换为纯文本会删除标记。

示例

此示例演示如何将文本斜体化。

<i>This is italicized Text</i>

<美国>

<u>带下划线的文本</u>

此标记请求带下划线的文本。 <b>、<i> 和 <u> 可以嵌套为混合属性。

转换为纯文本会删除标记。

示例

此示例演示如何为文本添加下划线。

<u>This is underlined Text</u>

示例

此示例演示如何将标记合并为加粗、下划线和斜体文本。

<b><u><i>This is bold, underlined and italizized text. </i></u></b> 

<col>

<col fg=“name” bg=“name”>text</col>

请求文本的前景色和背景色。 颜色作为已知颜色的名称而不是绝对值提供,因为这样客户就可以控制他们看到的颜色类型。 当前颜色名称 (默认值仅适用于 WinDbg) 。

前台和背景元素标记

设置 说明/示例

wbg - Windows 背景

wfg - Windows 前台

默认窗口背景和前景色。 默认为窗口和窗口文本的系统颜色。

<col fg=“wfg” bg=“wbg”> 这是标准的前景 / 背景文本 </col>

clbg - 当前行前景

clfg - 当前线条背景

当前线条背景和前景色。 默认为突出显示和突出显示文本的系统颜色。

<col fg=“clfg” bg=“clbg”> 测试文本 - Current Line</col>

empbg - 强调的背景

emphfg - 强调的前景

强调的文本。 默认为浅蓝色。

<col fg=“empfg” bg=“empbg”> 这是强调前景 / 背景文本 </col>

subbg - subdued 背景

subfg- Subdued 前台

subdued text。 默认为非活动描述文字文本和非活动字幕的系统颜色。

<col fg=“subfg” bg=“subbg”> 这是 subdued 前台 / 背景文本 </col>

normbg - 普通背景

normfg - 正常前景

普通

<col fg=“normfg” bg=“normbg”> 测试文本 - Normal (normfg / normbg) </col>

warnbg - 警告背景

warnfg - 警告前景

警告

<col fg=“warnfg” bg=“warnbg”> 测试文本 - 警告 (warnfg / warnbg) </col>

errbg - 错误背景

errfg - 前台错误

错误

<col fg=“errfg” bg=“errbg”> 测试文本 - 错误 (errfg / errbg) </col>

verbbg - 详细背景

verbfg - 详细前景

详细

<col fg=“verbfg” bg=“verbbg”> 测试文本 - Verbose (verbfg / verbbg) </col>

源代码单元素标记

srcnum - 源数值常量

源元素颜色。

<col fg=“srcnum” bg=“wbg”> 测试文本 - srcnum </col>

srcchar - 源字符常量

<col fg=“srcchar” bg=“wbg”> 测试文本 - srcchar </col>

srcstr - 源字符串常量

<col fg=“srcstr” bg=“wbg”> 测试文本 - srcstr </col>

srcid -源标识符

<col fg=“srcid ” bg=“wbg”> 测试文本 - srcid </col>

srckw - Keyword

<col fg=“srckw” bg=“wbg”> 测试文本 - srckw </col>

srcpair - 源大括号或匹配的符号对

<col fg=“srcpair” bg=“empbbg”> 测试文本 - srcpair </col>

srccmnt - 源注释

<col fg=“srccmnt” bg=“wbg”> 测试文本 - srccmnt </col>

srcdrct - Source 指令

<col fg=“srcdrct” bg=“wbg”> 测试文本 - srcdrct </col>

srcspid - 源特殊标识符

<col fg=“srcspid” bg=“wbg”> 测试文本 - srcspid </col>

srcannot - 源注释

<col fg=“srcannot” bg=“wbg”> Test Text - srcannot </col>

已更改 - 已更改数据

用于自上一个停止点以来已更改的数据,例如 WinDbg 中的更改寄存器。 默认为红色。

<col fg=“changed” bg=“wbg”> 测试文本 - Changed</col>

DML 示例代码

此示例代码演示了以下内容。

  • 调用调试命令
  • 实现右键单击命令
  • 实现将鼠标悬停在文本上
  • 使用颜色和格式文本
<col fg="srckw" bg="wbg"> <b>
*******************************************************
*** Example debug commands for crash dump analysis ****
*******************************************************
</b></col>
<col fg="srcchar" bg="wbg"><i>
**** Hover over commands for additional information ****
        **** Right-click for command help ****
</i></col>

<col fg="srccmnt" bg="wbg"><b>*** Common First Steps for Crash Dump Analysis ***</b> </col>
<link cmd=".symfix" alt="Set standard symbol path using .symfix">.symfix<altlink name="Help about .symfix" cmd=".hh .symfix" /> </link> - Set standard symbol path
<link cmd=".sympath+ C:\Symbols" alt="This link adds additional symbol directories">.sympath+ C:\Symbols<altlink name="Help for .sympath" cmd=".hh .sympath" /> </link> - Add any additional symbol directories, for example C:\Symbols
<link cmd=".reload /f" alt="This link reloads symbols">.reload /f<altlink name="Help for .reload" cmd=".hh .reload" /> </link> - Reloads symbols to make sure they are in good shape
<link cmd="!analyze -v" alt="This link runs !analyze with the verbose option">!analyze -v<altlink name="Help for !analyze" cmd=".hh !analyze" /> </link> - Run !analyze with the verbose option
<link cmd="vertarget" alt="This link runs checks the target version">vertarget<altlink name="Help for vertarget" cmd=".hh vertarget" /></link> - Check the target version
<link cmd="version" alt="This link displays the versions in use">version<altlink name="Help for version" cmd=".hh version" /></link> - Display the versions in use
<link cmd=".chain /D" alt="This link runs .chain">.chain /D<altlink name="Help for .chain" cmd=".hh .chain" /></link> - Use the .chain /D command to list debugger extensions
<link cmd="kM" alt="This link displays the stack backtrace using DML">kD<altlink name="Help for k" cmd=".hh k, kb, kc, kd, kp, kP, kv (Display Stack Backtrace)" /> </link> - Display the stack backtrace using DML rendering
<link cmd="lmD" alt="This link will run the list modules command and display the output in DML format">LmD<altlink name="Help for lmD" cmd=".hh lm" /> </link> - List modules command and display the output in DML format
<link cmd=".help /D" alt="Display help for commands">.help /D <altlink name="Help for .dot commands" cmd=".hh commands" /></link> - Display help for commands in WinDbg
<link cmd=".hh" alt="Start help">.hh<altlink name="Debugger Reference Help".hh Contents" cmd=".hh Debugger Reference" /></link> - Start help

<col fg="srccmnt" bg="wbg"><b>*** Registers and Context ***</b></col>
<link cmd="r" alt="This link displays registers">r<altlink name="Help about r command" cmd=".hh r" /></link>  - Display registers
<link cmd="dt nt!_CONTEXT" alt="This link displays information about nt_CONTEXT">dt nt!_CONTEXT<altlink name="Help about the dt command" cmd=".hh dt" /></link> - Display information about nt_CONTEXT
<link cmd="dt nt!_PEB" alt="This link calls the dt command to display nt!_PEB">dt nt!_PEB<altlink name="Help about dt command" cmd=".hh dt" /></link> - Display information about the nt!_PEB
<link cmd="ub" alt="This link unassembles backwards">ub<altlink name="Help about ub command" cmd=".hh u, ub, uu (Unassemble)" /></link> - Unassemble Backwards

<col fg="srcchar" bg="wbg"><i>
**** Note: Not all of the following commands will work with all crash dump data ****
</i></col>
<col fg="srccmnt" bg="wbg"><b>*** Device Drivers ***</b></col>
<link cmd="!devnode 0 1" alt="This link displays the devnodes">!devnode 0 1<altlink name="Help about !devnode command" cmd=".hh !devnode" /></link> - Display devnodes
<link cmd=".load wdfkd.dll;!wdfkd.help" alt="Load wdfkd extensions and display help">.load wdfkd.dll;!wdfkd.help<altlink name="Help about the wdfkd extensions" cmd=".hh !wdfkd" /></link> - Load wdfkd extensions and display help
<link cmd="!wdfkd.wdfldr" alt="This link displays !wdfkd.wdfldr">!wdfkd.wdfldr<altlink name="Help about !wdfkd.wdfldr" cmd=".hh !wdfkd.wdfldr" /></link>  - Display WDF framework driver loader information
<link cmd="!wdfkd.wdfumtriage" alt="This link displays !wdfkd.umtriage">!wdfkd.umtriage<altlink name="Help about !wdfkd.umtriage" cmd=".hh !wdfkd_wdfumtriage" /></link> - Display WDF umtriage driver information

<col fg="srccmnt" bg="wbg"><b>*** IRPs and IRQL ***</b></col>
<link cmd="!processirps" alt="This link displays process IRPs">!processirps<altlink name="Help about !processirps command" cmd=".hh !processirps" /></link> - Display process IRPs
<link cmd="!irql" alt="This link displays !irql">!irql<altlink name="Help about !irql command" cmd=".hh !irql" /></link> - Run !irql

<col fg="srccmnt" bg="wbg"><b>*** Variables and Symbols ***</b></col>
<link cmd="dv" alt="This link calls the dv command">dv<altlink name="Help about dv command" cmd=".hh dv" /></link> - Display the names and values of all local variables in the current scope

<col fg="srccmnt" bg="wbg"><b>*** Threads, Processes, and Stacks ***</b></col>
<link cmd="!threads" alt="This link displays threads">!threads<altlink name="Help about the !threads command" cmd=".hh !threads" /></link> - Display threads
<link cmd="!ready 0xF" alt="This link runs !ready 0xF">!ready 0xF<altlink name="Help about the !ready command" cmd=".hh !ready" /></link> - Display threads in the ready state
<link cmd="!process 0 F" alt="This link runs !process 0 F ">!process 0 F<altlink name="Help about the !process command" cmd=".hh !process" /></link> - Run !process 0 F
<link cmd="!stacks 2" alt="This link displays stack information using !stacks 2 ">!stacks 2<altlink name="Help about the !stacks command" cmd=".hh !stacks" /></link> - Display stack information using !stacks 2
<link cmd=".tlist" alt="This link displays a process list using TList ">tlist<altlink name="Help about the TList command" cmd=".hh .tlist" /></link> - Display a process list using tlist
<link cmd="!process" alt="This link displays process ">!process<altlink name="Help about the !process command" cmd=".hh !process" /></link> - Display process information
<link cmd="!dml_proc" alt="This link displays process information with DML rendering.">!dml_proc<altlink name="Help about the !dml_proc command" cmd=".hh !dml_proc" /></link> - Display process information with DML rendering

此示例代码演示了颜色和格式标记的使用。

*** Text Tag Examples ****

<b>This is bold text</b>
<u>This is underlined text</u>
<i>This is italizized text</i>
<b><u><i>This is bold, underlined and italizized text</i></u></b>

<b>Color Tag Examples</b>
<col fg="wfg" bg="wbg"> This is standard foreground / background text </col>
<col fg="empfg" bg="empbg"> This is emphasis foreground / background text </col>
<col fg="subfg" bg="subbg"> This is subdued foreground / background text </col>
<col fg="clfg" bg="clbg"> Test Text - Current Line</col>

<b>Other Tags Sets</b>
<col fg="normfg" bg="normbg"> Test Text - Normal (normfg / normbg) </col>
<col fg="warnfg" bg="warnbg"> Test Text - Warning (warnfg / warnbg) </col>
<col fg="errfg" bg="errbg"> Test Text - Error (errfg / errbg) </col>
<col fg="verbfg" bg="verbbg"> Test Text - Verbose (verbfg / verbbg) </col>

<b>Changed Text Tag Examples</b>
<col fg="changed" bg="wbg"> Test Text - Changed</col>

<b>Source Tags - using wbg background</b>
<col fg="srcnum" bg="wbg"> Test Text - srcnum  </col>
<col fg="srcchar" bg="wbg"> Test Text - srcchar  </col>
<col fg="srcstr" bg="wbg"> Test Text - srcstr  </col>
<col fg="srcid " bg="wbg"> Test Text - srcid   </col>
<col fg="srckw" bg="wbg"> Test Text - srckw </col>
<col fg="srcpair" bg="empbbg"> Test Text - srcpair </col>
<col fg="srccmnt" bg="wbg"> Test Text - srccmnt  </col>
<col fg="srcdrct" bg="wbg"> Test Text - srcdrct </col>
<col fg="srcspid" bg="wbg"> Test Text - srcspid </col>
<col fg="srcannot" bg="wbg"> Test Text - srcannot </col>

<b>Source Tags - using empbg background</b>
<col fg="srcnum" bg="empbg"> Test Text - srcnum  </col>
<col fg="srcchar" bg="empbg"> Test Text - srcchar  </col>
<col fg="srcstr" bg="empbg"> Test Text - srcstr  </col>
<col fg="srcid " bg="empbg"> Test Text - srcid   </col>
<col fg="srckw" bg="empbg"> Test Text - srckw </col>
<col fg="srcpair" bg="empbbg"> Test Text - srcpair </col>
<col fg="srccmnt" bg="empbg"> Test Text - srccmnt  </col>
<col fg="srcdrct" bg="empbg"> Test Text - srcdrct </col>
<col fg="srcspid" bg="empbg"> Test Text - srcspid </col>
<col fg="srcannot" bg="empbg"> Test Text - srcannot </col>

<b>Source Tags - using subbg background</b>
<col fg="srcnum" bg="subbg"> Test Text - srcnum  </col>
<col fg="srcchar" bg="subbg"> Test Text - srcchar  </col>
<col fg="srcstr" bg="subbg"> Test Text - srcstr  </col>
<col fg="srcid " bg="subbg"> Test Text - srcid   </col>
<col fg="srckw" bg="subbg"> Test Text - srckw </col>
<col fg="srcpair" bg="subbg"> Test Text - srcpair </col>
<col fg="srccmnt" bg="subbg"> Test Text - srccmnt  </col>
<col fg="srcdrct" bg="subbg"> Test Text - srcdrct </col>
<col fg="srcspid" bg="subbg"> Test Text - srcspid </col>
<col fg="srcannot" bg="subbg"> Test Text - srcannot </col>

对 dbgeng 接口的 DML 添加

调试器引擎和扩展 API 提供了一个接口,用于使用调试器引擎创建自定义应用程序。 还可以编写将在 WinDbg、KD、CDB 和 NTSD 中运行的自定义扩展。 有关详细信息,请参阅 编写 DbgEng 扩展。 本部分介绍调试器引擎接口的可用 DML 增强功能。

dbgeng 已有一组处理输入方法和输出接口的文本,使用 DML 只需要指定输入和输出文本中携带的内容类型。

向 dbgeng 提供 DML 内容

输出控制标志DEBUG_OUTCTL_DML指示 dbgeng 方法生成的文本应作为 DML 内容处理。 如果未提供此标志,则文本被视为纯文本上下文。 DEBUG_OUTCTL_DML可以与以下方法一起使用。

对于有效字符,给定的文本必须遵循 DML 规则。

所有输出例程都已得到增强,以允许新的格式说明符 %[h|w]Y{t}。 此格式说明符具有字符串指针作为参数,指示给定文本是纯文本,应在输出处理期间转换为 DML 格式。 这为调用方提供了一种在 DML 内容中包含纯文本的简单方法,而无需自行预转换为 DML 格式。 h 和 w 限定符指示 ANSI 或 Unicode 文本,与 %s 一样。

下表汇总了 %Y 格式说明符的使用。

%Y{t}:带引号的字符串。 如果输出格式 (第一个参数) 为 DML,则会将文本转换为 DML。

%Y{T}:带引号的字符串。 无论输出格式如何,始终将文本转换为 DML。

%Y{s}:无引号字符串。 如果输出格式 (第一个参数) 为 DML,则会将文本转换为 DML。

%Y{S}:无引号字符串。 无论输出格式如何,始终将文本转换为 DML。

%Y{as}:ULONG64。 添加一个空字符串或 9 个字符的间距,以填充调试器格式化指针字段的高 32 位部分。 额外空间输出 9 个空格,其中包括上 8 个零加上 ' 字符。

%Y{ps}:ULONG64。 用于填充调试器格式的指针字段的额外空间 (包括上 8 个零加上字符) 。

%Y{l}:ULONG64。 地址作为源行信息。

此代码片段演示了 %Y 格式说明符的用法。

HRESULT CALLBACK testout(_In_ PDEBUG_CLIENT pClient, _In_ PCWSTR /*pwszArgs*/)
{
    HRESULT hr = S_OK;

    ComPtr<IDebugControl4> spControl;
    IfFailedReturn(pClient->QueryInterface(IID_PPV_ARGS(&spControl)));

    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{t}: %Y{t}\n", L"Hello <World>");
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{T}: %Y{T}\n", L"Hello <World>");
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{s}: %Y{s}\n", L"Hello <World>");
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{S}: %Y{S}\n", L"Hello <World>");

    spControl->ControlledOutputWide(0, DEBUG_OUTPUT_NORMAL, L"TEXT/NORMAL Y{t}: %Y{t}\n", L"Hello <World>");
    spControl->ControlledOutputWide(0, DEBUG_OUTPUT_NORMAL, L"TEXT/NORMAL Y{T}: %Y{T}\n", L"Hello <World>");
    spControl->ControlledOutputWide(0, DEBUG_OUTPUT_NORMAL, L"TEXT/NORMAL Y{s}: %Y{s}\n", L"Hello <World>");
    spControl->ControlledOutputWide(0, DEBUG_OUTPUT_NORMAL, L"TEXT/NORMAL Y{S}: %Y{S}\n", L"Hello <World>");

    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{a}: %Y{a}\n", (ULONG64)0x00007ffa7da163c0);
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{as} 64bit   : '%Y{as}'\n", (ULONG64)0x00007ffa7da163c0);
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{as} 32value : '%Y{as}'\n", (ULONG64)0x1);

    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{ps} 64bit   : '%Y{ps}'\n", (ULONG64)0x00007ffa7da163c0);
    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{ps} 32value : '%Y{ps}'\n", (ULONG64)0x1);

    spControl->ControlledOutputWide(DEBUG_OUTCTL_DML, DEBUG_OUTPUT_NORMAL, L"DML/NORMAL Y{l}: %Y{l}\n", (ULONG64)0x00007ffa7da163c0);

    return hr;

}

此示例代码将生成以下输出。

0:004> !testout
DML/NORMAL Y{t}: "Hello <World>"
DML/NORMAL Y{T}: "Hello <World>"
DML/NORMAL Y{s}: Hello <World>
DML/NORMAL Y{S}: Hello <World>
TEXT/NORMAL Y{t}: "Hello <World>"
TEXT/NORMAL Y{T}: "Hello &lt;World&gt;"
TEXT/NORMAL Y{s}: Hello <World>
TEXT/NORMAL Y{S}: Hello &lt;World&gt;
DML/NORMAL Y{a}: 00007ffa`7da163c0
DML/NORMAL Y{as} 64bit   : '         '
DML/NORMAL Y{as} 32value : '         '
DML/NORMAL Y{ps} 64bit   : '        '
DML/NORMAL Y{ps} 32value : '        '
DML/NORMAL Y{l}: [d:\th\minkernel\kernelbase\debug.c @ 443]

其他控件标志DEBUG_OUTCTL_AMBIENT_DML,允许在不修改任何输出控件属性的情况下规范 DML 上下文文本。 DEBUG_OUTCTL_AMBIENT_TEXT还添加为以前存在的DEBUG_OUTCTL_AMBIENT更具描述性的别名。 输出控制标志在 dbgeng.h 中定义。

#define DEBUG_OUTCTL_DML               0x00000020

// Special values which mean leave the output settings
// unchanged.
#define DEBUG_OUTCTL_AMBIENT_DML       0xfffffffe
#define DEBUG_OUTCTL_AMBIENT_TEXT      0xffffffff

// Old ambient flag which maps to text.
#define DEBUG_OUTCTL_AMBIENT           DEBUG_OUTCTL_AMBIENT_TEXT

从调试对象提供 DML 内容

dbgeng 已得到增强,可扫描调试对象输出中是否有特殊标记 – 指示应将调试对象输出片段中的剩余文本视为 DML。 模式更改仅适用于单个调试对象输出(例如单个 OutputDebugString 字符串),不是全局模式开关。

此示例演示纯输出和 DML 输出的混合。

OutputDebugString(“This is plain text\n<?dml?>This is <col fg=\”emphfg\”>DML</col> text\n”);

生成的输出将具有一行纯文本,后跟一行 DML,其中首字母缩略词 DML 以不同的颜色显示。

IDebugOutputCallbacks2

IDebugOutputCallbacks2 允许 dbgeng 接口客户端接收用于演示的完整 DML 内容。 IDebugOutputCallbacks2 是 IDebugOutputCallbacks (而不是 IDebugOutputCallbacksWide) 的扩展,以便它可以传递到现有的 SetOutputCallbacks 方法。 引擎将为 IDebugOutputCallbacks2 执行 QueryInterface,以查看传入输出回调对象支持哪个接口。 如果对象支持 IDebugOutputCallbacks2,则所有输出将通过扩展的 IDebugOutputCallbacks2 方法发送;将不使用基本 IDebugOutputCallbacks::Output 方法。

新方法包括:

  • IDebugOutputCallbacks2::GetInterestMask – 允许回调对象描述它想要接收哪些类型的输出通知。 基本选择是纯文本内容 (DEBUG_OUTCBI_TEXT) 和 DML 内容 (DEBUG_OUTCBI_DML) 。 此外,回调对象还可以请求 (DEBUG_OUTCBI_EXPLICIT_FLUSH) 显式刷新的通知。

  • IDebugOutputCallbacks2::Output2 – 所有 IDebugOutputCallbacks2 通知都通过 Output2 发出。 哪个参数指示在 Flags、Arg 和 Text 参数携带通知有效负载时传入的通知类型。 通知包括:

    • DEBUG_OUTCB_TEXT - 纯文本输出。 标志来自 DEBUG_OUTCBF_*,Arg 是输出掩码,Text 是纯文本。 仅当在利益掩码中提供了DEBUG_OUTCBI_TEXT时,才会收到此消息。

    • DEBUG_OUTCB_DML - DML 内容输出。 标志来自 DEBUG_OUTCBF_*,Arg 是输出掩码,Text 是 DML 内容。 仅当在利益掩码中提供了DEBUG_OUTCBI_DML时,才会收到此消息。

    • DEBUG_OUTCB_EXPLICIT_FLUSH – 调用方调用 FlushCallbacks 时没有缓冲文本。 通常,刷新缓冲文本时,将设置DEBUG_OUTCBF_COMBINED_EXPLICIT_FLUSH标志,将两个通知折叠为一个。 如果没有缓冲文本,则发送仅刷新通知。

兴趣掩码标志在 dbgeng.h 中定义,如下所示。

// IDebugOutputCallbacks2 interest mask flags.
//
// Indicates that the callback wants notifications
// of all explicit flushes.
#define DEBUG_OUTCBI_EXPLICIT_FLUSH 0x00000001
// Indicates that the callback wants
// content in text form.
#define DEBUG_OUTCBI_TEXT           0x00000002
// Indicates that the callback wants
// content in markup form.
#define DEBUG_OUTCBI_DML            0x00000004

#define DEBUG_OUTCBI_ANY_FORMAT     0x00000006

请注意,如果输出对象可以同时处理文本和 DML 内容,则可以注册它们。 在回调的输出处理期间,引擎将选取减少转换的格式,因此支持这两种格式可能会减少引擎中的转换。 不过,这不是必要的,并且仅支持一种格式是预期的操作模式。

自动转换

dbgeng 将在必要时自动在纯文本和 DML 之间转换。 例如,如果调用方将 DML 内容发送到引擎,则引擎将针对仅接受纯文本的所有输出客户端将其转换为纯文本。 或者,对于仅接受 DML 的所有输出回调,引擎会将纯文本转换为 DML。

另请参阅

使用调试器标记语言