工具介绍
CDB.exe 及 ADPlus.exe 在 WinDbg.exe 同目录下;
CDB.exe 是 Windows 控制台调试器,不具有图形用户界面;
ADPlus.exe 自动化了 CDB.exe 的调试操作;
ADPlus.exe 可以部署在生产环境,对性能几乎无影响;
ADPlus.exe 可以根据配置自动生成内存转储和日志文件。
监视异常类型:
- 无效的句柄
- 非法指令
- 整数被零除
- 浮点数被零除
- 整数溢出
- 无效的锁定顺序
- 访问冲突
- 堆栈溢出
- C + + EH 异常
- 未知的异常
适用场景
客户机、服务器等需要对性能影响较小的环境;
不能使用图形界面操作调试器;
需要自动化记录日志以及在程序异常崩溃时dump。
工具获取
WinSDK安装程序
运行安装程序后,仅勾选安装 “Debugging Tools for Windows”
用法示例
示例一:
ADPlus.exe -crash -p PID -o DumpFilePath
解释:ADPlus 使用调试器 CDB 附加到进程ID为 PID 的进程,在进程崩溃时输出 dump 文件到 DumpFilePath 路径。
注意:DumpFilePath 是一个文件夹,不能是文件。
示例二:
ADPlus.exe -crash -o C:\Users\Administrator\Desktop -NoDumpOnFirst -MiniOnSecond -lcqd -pmn ProcessName.exe
解释:
ADPlus 使用调试器监视进程名为 ProcessName.exe 的进程启动,并在启动后附加;
NoDumpOnFirst 在程序第一次异常时不进行 dump ,但是会记录日志信息;
MiniOnSecond 在程序第二次异常时,进行小型转储并记录日志;
在进程崩溃时输出 dump 文件到 DumpFilePath 路径;
lcqd 将调试器的最后一个命令设置为退出并分离。
示例三:
ADPlus.exe -c FullPath\XXX.xml
解释:ADPlus 读取 XXX.xml 配置文件。
注意:
使用它可以比命令行选项更详细地配置 ADPlus,可以通过配置文件创建新的自定义关键字;
可以在配置文件中设置所有命令行选项,并且可以结合使用命令行选项和配置文件;
当配置文件 XXX.xml 与 ADPlus.exe 在同一目录时,可省略路径;
当XXX.xml 的完整路径中有空格时,使用双引号包起路径;
XXX.xml 文件中,最好不要出现注释,否则在大型项目中可能会产生未知的 BUG。
命令行语法
-? or -help
显示摘要帮助。
-HelpConfig
显示内置关键字和默认行为设置。
-Crash
附加到流程,并保持连接状态,等待异常或其他事件发生;
通常在故障排除崩溃时使用,但可以在更多情况下使用。
-Hang
附加到进程,进行内存转储并分离;用于挂起情况;
在程序运行中进行 dump。
-o <输出目录>
存储日志和内存转储的位置。
-c <配置文件>
读取 ADPlus 配置文件。
-p <进程ID>
标识要附加的进程 ID;可以多次使用。
-pn <进程名称>
标识要附加的进程名称。 ProcessName 可以包含 * 通配符;
因此,* note * 会附加到 notepad,onenote 等进程上。可多次使用。
-po <进程名称>
与 –pn 相同,但表示可选过程;
如果 –pn 记事本如果未运行,则将失败,而 -po 记事本将不会失败。
-pmn <进程名称>
过程监视器。 Adplus 将继续运行,并监视名为 ProcessName 的进程是否启动并附加到该进 程。
仅对 –crash 有效。
-sc <进程名> [参数]
将导致 ProcessName 由调试器启动
这必须是最后一个选项,因为所有其余参数都被视为此过程的参数。
-iis
选择与IIS相关的所有进程,例如 inetinfo.exe,dllhost.exe 等。
-y <符号路径>
设置调试器的符号路径;
可以提供多个路径,以分号分隔。
-yp <符号路径>
添加符号路径;
可以提供多个路径,以分号分隔。
-mss <本地缓存的符号路径>
本地缓存符号的路径,将 Microsoft 符号服务器下载的符号文件保存到该路径。
-FullOnFirst
将首次机会异常的默认行为更改为完全转储。
-MiniOnSecond
将第二次机会异常的默认行为更改为小型转储。
-NoDumpOnFirst
更改首次机会异常的默认行为以不发出转储。
-NoDumpOnSecond
更改第二次机会异常的默认行为以不发出转储。
-Do
仅转储;更改默认的行为,以只进行内存转储;
不会记录堆栈、线程、时间、事件等其他信息。
-r <数量> <间隔(秒)>
以给定的时间间隔重复连接;仅在(Hang)挂起模式下使用;
例如:-r 3 30 以30秒的间隔运行 ADPlus 3次。
-Gs
表示只需要生成脚本;
使用此选项时,不应包括任何进程选项;
如果要创建可在另一台计算机上手动使用的脚本,则使用。
-CTCF
使用 CTL+C 生成完整转储。
-CTCFB
使用 CTL+C 生成完整转储,然后中断。
-CTCV
使 CTL+C 无效;只是在调试器中 中断。
-lcq
将脚本的最后一个命令设置为 Q(退出);
这是默认行为。
-lcg
将脚本的最后一个命令设置为 G (运行)。
-lcgn
将脚本的最后一个命令设置为 GN(不处理)。
-lcqd
将脚本的最后一个命令设置为 QD(退出并分离)。
-lcv
将脚本的最后一个命令设置为 Void;
只是在调试器中 中断。
-ce <异常码>
添加要监视的自定义异常。
-bp <地址[;行为]>
添加要监视的断点;动作可以是任何已知的关键字;
例如:-bp MyModule!MyClass::MyMethod;MiniDump
-dbg <调试器>
选择要使用的调试器;可以是 cdb,windbg 或 ntsd;
默认为 cdb。
-dp <调试器路径>
用于 ADPlus 与调试器不在同目录的情况。
-q2
将所有第二次机会异常的返回动作设置为 Q(退出)。
-g2
将所有第二次机会异常的返回操作设置为 GN(不处理)。
脚本配置
脚本配置中只列出了常用的部分,其他内容请在使用ADPlus前阅读参考文档中所列ADPlus.doc
示例:
ADPlus Version="2">
<Settings>
<Runmode>Crash</Runmode>
<OutputDir>LogPath</OutputDir> <!-- 修改输出目录 存储日志和内存转储的位置 -->
<ProcessToMonitor>ProcessName.exe</ProcessToMonitor> <!-- 修改进程名称 监视名为ProcessName的进程是否启动并附加到该进程 -->
</Settings>
<Exceptions>
<All>
<Actions1>Log;Time;Stack</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>Q</ReturnAction2>
</All>
<Exception Code="epr"> <!-- 进程关闭 -->
<Actions1>Log;Time;EventLog;Stacks;ThreadUsage</Actions1>
<ReturnAction1>Q</ReturnAction1>
</Exception>
</Exceptions>
</ADPlus>
其它异常码及处理示例:
<Exception Code="av"><!-- 访问冲突 -->
<Actions1>Log;Time;Stack;MiniDump;EventLog</Actions1>
<ReturnAction1>GN</ReturnAction1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="ch"><!-- 无效句柄 -->
<Actions1>Log;Time;Stack;MiniDump;EventLog</Actions1>
<ReturnAction1>GN</ReturnAction1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="ii"><!-- 非法指令 -->
<Actions1>Log;Time;Stack;MiniDump;EventLog</Actions1>
<ReturnAction1>GN</ReturnAction1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="dz"><!-- 整数除零 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="c000008e"><!-- 浮点数除零 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="iov"><!-- 整数溢出 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="lsq"><!-- 锁序列无效 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="sov"><!-- 堆栈溢出 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="aph"><!-- 应用程序挂起 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="dm"><!-- 数据未对齐 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="gp"><!-- 保护页违规 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="ip"><!-- 页内IO错误 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="isc"><!-- 无效的系统调用 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="sbo"><!-- 堆栈溢出 -->
<Actions1>VOID</Actions1>
<Actions2>Log;Time;Stack;MiniDump;EventLog</Actions2>
<ReturnAction1>GN</ReturnAction1>
<ReturnAction2>GN</ReturnAction2>
</Exception>
<Exception Code="epr"><!-- 进程关闭 -->
<Actions1>Log;Time;</Actions1>
<ReturnAction1>Q</ReturnAction1>
</Exception>
Settings 部分
<Settings>
<Option> option </Option>
<Runmode> option </Runmode>
<LastScriptCommand> option </LastScriptCommand>
<OutputDir> path </OutputDir>
<ProcessID> procID </ProcessID>
<ProcessName> procname </ProcessName>
<ProcessNameOptional> procname </ProcessNameOptional>
<ProcessToMonitor> procname </ProcessToMonitor>
<Spawn> command arguments</Spawn>
<Sympath> symbolspath </Sympath>
<SympathPlus> symbolspath </SympathPlus>
<MSSLocalCache> local_cache_path </MSSLocalCache>
<Debugger>option</Debugger>
<IISAdd>proc1;proc2</IISAdd>
<IISSet>proc1;proc2</IISSet>
<Repeat Repeats="Quantity" Interval="seconds" />
<NotifyList> machine1;machine2</NotifyList>
<CustomDump> option </CustomDump>
</Settings>
可以接受的值
<Option> option </Option>
option = FullOnFirst | MiniOnSecond | NoDumpOnFirst | IIS | DumpOnly | ExtensionInteraction | QuitOnSecond | GoOnSecond
<Runmode> option </Runmode>
Option = Crash | Hang
<LastScriptCommand> option </LastScriptCommand>
Option = Q | QD | G | GN | Void
<Debugger>option</Debugger>
Option = Windbg | CDB | NTSD
<CustomDump> option </CustomDump>
Option = 调试器的转储选项,例如: /ma.
<IISAdd> proc1 </IISAdd>
将 proc1.exe 添加到与 IIS 相关的进程列表中。
<IISSet> proc1;proc2 </IISSet>
重置与 IIS 相关的进程列表。
<NotifyList> machine1; machine2 </NotifyList>
定义在以下情况下要通知的计算机列表
通知动作已执行。
(这似乎在Vista上不起作用)
Exceptions 部分
<Exceptions>
<Exception Code="SomeCode"> or
<NewException Code="SomeCode" Name="SomeName"> or
<AllExceptions> or
<AllEvents> or
<All>
<Actions1>actions</Actions1>
<Actions2> actions </Actions2>
<ReturnAction1> GN | GH | Q </ReturnAction1>
<ReturnAction2> GN | GH | Q </ReturnAction2>
</Exception> or </NewException> or </AllExceptions> or
</AllEvents> or </All>
<Include> filename </Include>
</Exceptions>
可以接受的值
<Actions1>actions</Actions1>
actions 一组已知关键字;
可选:Log;Time;Stack;EventLog;ThreadUsage;MiniDump;;FullDump;Heap;THREADTIME;VOID等
Breakpoints 部分
<Breakpoints>
<Breakpoint Name= "MyBP" Address="Module!func+0x12" [Type="BP|BU"] [Passes="100"]>
<Actions> actions </Actions>
<ReturnAction> G|Q|QD </ReturnAction>
</Breakpoint>
<Include> filename </Include>
</Breakpoints>
可以接受的值
<Actions1>actions</Actions1>
actions 一组已知关键字;
可选:Log;Time;Stack;EventLog;ThreadUsage;MiniDump;;FullDump;Heap;THREADTIME;VOID等
参考文档
使用前先阅读以下文档
[1]: 调试器同目录下 adplus.doc 文档
[2]: https://support.microsoft.com/zh-cn/help/286350/how-to-use-adplus-vbs-to-troubleshoot-hangs-and-crashes