应用程序验证程序(AppVerifier)是用于非托管代码的运行时验证工具,可帮助查找微妙的编程错误、安全问题和有限的用户帐户特权问题,这些问题可能难以识别常规应用程序测试技术。
若要交付可靠的 Windows 应用程序,请执行以下操作:
- 使用调试程序下的应用程序验证工具以及完整页堆测试以非托管(原生)代码编写的应用程序,然后再将其发布给客户。
- 按照应用程序验证工具提供的步骤解决异常情况。
- 发布应用程序后,定期监视收集的应用程序故障报告,例如 Windows 错误报告(如果可用)。
线程池检查在“基本信息”检查标题下默认启用。 由于此设置包含在默认设置中,用户只需在其代码上运行应用程序验证程序,并使用默认设置来利用这些检查和其他重要检查。
配置应用程序验证程序
调试器设置
正在验证的应用程序应在用户模式调试器下运行,或者系统应在内核调试器下运行,因为它会在发生错误时中断调试器。 有关更多详细信息,请参阅 应用程序验证程序 - 调试应用程序验证程序停止。
设置
无法为正在运行的进程启用应用程序验证程序。 因此,需要按如下所述进行设置,然后启动应用程序。 这些设置是永久性的,直到显式删除。 因此,无论启动应用程序多少次,都会在删除设置之前启用 AppVerifier 启动。
使用应用程序验证程序基本测试
以下方案说明了建议的命令行和用户界面选项。 这些应在执行代码的所有测试期间运行,以确保完全覆盖。 这些方案的预期是,应用程序不会闯入调试器,并且所有测试都通过与在未启用 AppVerifier 的情况下运行时相同的通过率进行传递。
为要测试的应用程序(s)启用验证程序。 从命令行:appverif /verify MyApp.exe
。
在用户界面中:通过右键单击“应用程序”区域并选择“添加应用程序”来添加应用程序。 从“测试”区域选择“基本信息”。 单击“保存”按钮。
注释:
/verify 将启用基本测试
如果要测试 DLL,则必须为执行 DLL 的测试可执行文件启用应用程序验证程序。
单独运行验证层。 例如,在一个会话中启用所有基本信息,在另一个会话中启用所有 LuaPriv 检查。
运行执行应用程序的所有测试。
分析遇到的任何调试器中断。 如果发生中断,则需要了解它并修复它。 注意:帮助内容提供有关中断的详细信息以及如何调查它们。
完成后,删除所有设置。 从命令行:appverif /n MyApp.exe
。
在用户界面中,通过右键单击应用程序区域并选择“删除应用程序”来删除应用程序。 然后单击“保存”按钮。
堆损坏
Windows 系统上近 10% 的应用程序崩溃是由于堆损坏造成的。 这些崩溃几乎不可能在事后进行调试。 避免这些问题的最佳方法是使用应用程序验证工具中的页面堆功能进行测试。 页面堆有两种风格:“完整”和“轻型”。“完整”是默认风格;它将强制调试程序在检测到损坏时立即停止。 此功能必须在调试程序下运行。 不过,它也是最耗费资源的风格。 如果用户遇到计时问题,并且已在“完整”页面堆下运行方案,则将其设置为“轻型”可能会解决这些问题。 此外,在进程退出之前,轻型页面堆不会崩溃。 它确实提供了对分配的堆栈跟踪,但与利用“完整”对应项相比,诊断可能需要更长的时间。
使用 AppVerifier 低资源模拟(故障注入)
此方案的预期是应用程序不会闯入调试器。 如果不闯入调试器,则意味着无需解决任何错误。
测试的通过率可能会显著下降,因为随机故障注入引入到正常作中。
为应用程序启用应用程序验证程序低资源模拟(故障注入)。 从命令行:Appverif /verify MyApp.exe /faults
。 在用户界面中:通过右键单击“应用程序”区域并选择“添加应用程序”来添加应用程序。 从“测试”区域选择“低资源模拟”。 单击“保存”按钮。
注意:如果要测试 DLL,则可以对特定 DLL 应用低资源模拟(故障注入),而不是整个进程。 命令行格式为:
appverif /verify TARGET [/faults [PROBABILITY [TIMEOUT [DLL …]]]]
示例:
appverif /verify mytest.exe /faults 50000 1000 d3d9.dll
运行执行应用程序的所有测试
分析遇到的任何调试器中断。 如果发生中断,则需要了解它并修复它。
完成后,删除所有设置。 从命令行:appverif /n MyApp.exe。 在用户界面中:通过右键单击“应用程序”区域并选择“删除应用程序”,单击“保存”按钮来删除应用程序。
注意:在应用程序中使用和不使用故障注入练习时运行基本上不同的代码路径,因此必须运行这两种方案才能充分利用 AppVerifier。
将应用程序验证程序与 WOW64 配合使用
可以使用 32 位或 64 位版本的应用程序验证程序来验证 WOW64 下运行的 32 位应用程序。
分析 AppVerifier 数据
在 AppVerifier 分析期间创建的所有数据都以二进制格式存储在 %USERPROFILE%\AppVerifierLogs 文件夹中。 然后,可以通过用户界面或命令行将这些日志转换为 XML,以便进一步分析。
若要查看 XML 文件,可以使用任何工具来查看 XML,例如导入到 Microsoft Excel - 将 XML 文件导入到 Excel 中,并使用筛选器或数据透视表重新组织和分析收集的数据。
使用命令行
应用程序验证程序可以通过 UI 或命令行选项使用。
下面是如何使用命令行的示例(下面是详细信息):
appverif /verify TARGET [/faults [PROBABILITY [TIMEOUT [DLL …]]]]
appverif /verify notepad
appverif -enable LAYER … -for TARGET ... [-with [LAYER].PROPERTY=[VALUE] …]
appverif -disable LAYER ... -for TARGET ...
appverif -query LAYER ... -for TARGET ...
appverif –configure STOP ... -for TARGET ... [-with STOPPROPERTY=[VALUE] …]
appverif –logtofile {enable|disable}
若要为两个应用程序启用特定验证层的应用程序验证程序,请执行以下作:
appverif –enable Heaps Locks –for notepad.exe iexplore.exe
若要为目标 test.exe 启用两个名为 X 和 Y 的层,其属性为 X.DebugLevel 和 Y.DebugLevel:
appverif –enable X Y –for test.exe –with X.DebugLevel=1 Y.DebugLevel=2
若要禁用在应用程序上运行的所有检查,请执行以下作:
appverif -disable * -for notepad.exe
或者
appverif -delete settings -for notepad.exe
若要对所有进程全局启用或禁用应用程序验证程序日志记录,请执行以下作:
appverif –logtofile enable
appverif –logtofile disable
默认情况下为所有进程启用日志记录。
应用程序验证程序命令行语法
应用程序验证程序命令行用法:
-enable TEST ... -for TARGET ... [-with [TEST.]PROPERTY=VALUE ...]
-disable TEST ... -for TARGET ...
-query TEST ... -for TARGET ...
-configure STOP ... -for TARGET ... -with PROPERTY=VALUE...
-verify TARGET [-faults [PROBABILITY [TIMEOUT [DLL ...]]]]
-export log -for TARGET -with To=XML_FILE [Symbols=SYMBOL_PATH] [StampFrom=LOG_STAMP] [StampTo=LOG_STAMP] [Log=RELATIVE_TO_LAST_INDEX]
-delete {logs|settings} -for TARGET ...
-stamp log -for TARGET -with Stamp=LOG_STAMP [Log=RELATIVE_TO_LAST_INDEX]
-logtoxml LOGFILE XMLFILE
-installprovider PROVIDERBINARY
-sppath [PROTECTED_PROCESS_LOG_PATH]
-cppath
-logtofile [enable | disable]
命令行语法接受一个或多个层,并将它们应用于具有层的可选属性说明符的一个或多个目标。
appverif -enable LAYER ... -for TARGET ... [-with [LAYER].PROPERTY=[VALUE] …]
appverif -disable LAYER ... -for TARGET ...
appverif -query LAYER ... -for TARGET ...
appverif –configure STOP ... -for TARGET ... [-with STOPPROPERTY=[VALUE] …]
地点:
LAYER 是验证层的标准名称。 如果安装了新的验证程序提供程序,则会公开一个新的验证层名称,该名称将在命令行中使用。 示例层为堆、句柄或锁。
可以将 LAYER 设置为 * 以指定命令适用于所有层。
TARGET 是二进制名称(例如 notepad.exe)。 这是一个静态设置,该设置保存在注册表中,每当启动应用程序时,都会考虑这些设置。 对于 appverif –disable 命令,可以将 TARGET 设置为 * 以指定应禁用所有目标。
PROPERTY 是特定于命令行中提到的 LAYER 的属性名称。 例如,句柄层具有作为属性的跟踪。
VALUE 是属性的值。 值的类型取决于与属性关联的类型,并强制实施该值。 目前支持的类型包括:布尔值(true/false)、整数(C 表示法中的十进制/八进制/十六进制)、字符串和多字符串(包含 \0’ between strings and being terminated by
\0\0')。 如果未指定 VALUE,则表示用户想要删除该属性并将行为还原为该属性的默认值。
STOP 是要配置的验证程序停止问题的数字(decimal 或 hex in C 表示法)。 停止代码必须是唯一的(两个层不能使用相同的停止代码,因此工具本身将确定该停止所属的层)
STOPROPERTY 是验证程序停止可接受的属性名称。 如果未指定该值,则假定该属性必须被删除。 停止的允许属性是(有关更多详细信息,请参阅下面的配置验证程序停止):
- error.report
- 严重程度
- 味道
属性可由它们所属的层选择性地限定。 但是,如果命令行仅启用一个层,则不需要这样做。 例如,若要为目标 test.exe 启用两个名为 X 和 Y 的层,其中属性为 X.DebugLevel 和 Y.DebugLevel,命令为:
appverif –enable X Y –for test.exe –with X.DebugLevel=1 Y.DebugLevel=2
但是,如果启用了第 X 层,则可以使用未限定的属性名称:
appverif –enable X –for test.exe –with DebugLevel=1
属性名称和值之间的分隔符可以是 =
(等号)或 :
(冒号)。
杂项命令
appverif –query providers
appverif –delete logs –for TARGET ...
appverif –delete settings –for TARGET ...
从注册表中完全清除 TARGET。
appverif –stamp log –for Target –with Stamp=”LOG_STAMP”[Log= RELATIVE_TO_LAST_INDEX]
此命令将使用LOG_STAMP标记日志。 此标记可用于在 XML 窗体中查看日志时仅将日志的一部分标识为相关部分。
appverif –export log –for TARGET –with To=XML_FILE[Symbols=SYMBOL_PATH][Stamp=LOG_STAMP][StampTo=LOG_STAMP][Log=RELATIVE_TO_LAST_INDEX]
上述命令会将二进制日志导出到 xml 文件。 可选 Stamp 属性用于标识应将日志的哪个部分导出到 XML。 如果未指定,则将转换整个日志。 Log 属性具有可能的负整数值,表示应从最后一个值开始转换哪些日志文件(假定如果属性不存在)。 例如,连续启动 notepad.exe 三次。 若要访问创建的第一个日志,请在命令行中指定 Log=-2。
命令行的快捷方式
下面是快捷方式:
appverif /verify TARGET [/faults [PROBABILITY [TIMEOUT [DLL …]]]]
地点:
TARGET 的含义与上述含义相同。
PROBABILITY 是注入故障的概率。 必须是 0..1000000 范围内的值。 如果未指定默认值,则为 5%。
TIMEOUT 是在进程启动期间发生故障注入时时间间隔(以毫秒为单位)。 这样做是为了允许进程在发生错误之前正确启动。 如果未指定该值,则值为 500 毫秒。
DLL 是在进程中加载的模块的名称。 通常,这是动态库(扩展 .dll)的名称,但可以是 ActiveX(扩展名 .ocx)或其他可加载模块。
例子:
appverif /verify notepad.exe /faults 100000 1000 msvcrt.dll
为 notepad.exe 启用故障注入(每当启动时)。 故障的发生概率为 10%,在启动进程后只有 1000 毫秒,并且仅适用于从 msvcrt.dll启动的作。
启用故障注入详细信息
使用 /faults 命令行将仅为OLE_ALLOC和HEAP_ALLOC启用故障注入。 但是,可以使用命令行来配置要打开的错误注入类型。 例如,如果要将错误注入注册表或文件 API 作为 2%,请使用命令行:
appverif -enable lowres -for hello.exe -with registry=20000 file=20000
另一个示例:
appverif -query lowres -for hello.exe
Settings for hello.exe:
Test [lowres] enabled.
Include = *
Exclude =
TimeOut = 2000 (0x7D0)
WAIT = 0 (0x0)
HEAP_ALLOC = 20000 (0x4E20)
VIRTUAL_ALLOC = 0 (0x0)
REGISTRY = 20000 (0x4E20)
FILE = 20000 (0x4E20)
EVENT = 0 (0x0)
MAP_VIEW = 0 (0x0)
OLE_ALLOC = 20000 (0x4E20)
STACKS = false
配置验证程序停止
使用命令行(或用户界面)可以配置验证程序停止。 下面是利用的示例:
Appverif -configure STOP ... -for TARGET ... -with PROPERTY=VALUE ...
STOP 是停止代码,例如0x200 0x201
TARGET 是应用程序名称,例如 foo.exe
PROPERTY 可以是“ErrorReport”、“Severity”和“Flavor”之一
对于 ErrorReport,VALUE 可以是以下值的组合。
0x00000001表示停止处于活动状态。 (如果此位为零,则表示停止处于禁用状态)
0x00000020意味着停止将使用断点进入调试器。
0x00000040表示通过生成验证程序异常来停止进入调试器。
0x00000080意味着停止将记录在日志文件中。
0x00000100意味着此停止的堆栈跟踪将记录在日志文件中。
对于严重性,VALUE 可以是下列值之一。
0x00000003信息停止。
0x0000000F警告。
0x0000003F错误。
对于“风格”,值可以是以下值的组合。
0x00000002不可连续停止。
0x00000010此停止将只显示一次。 在测试运行中,将忽略以下时间。
例如,为 foo.exe 禁用停止0x2700,0x2701
Appverif –configure 0x2700 0x2701 –for foo.exe –with ErrorReport=0
将停止代码0x2700配置为中断调试器(默认情况下已关闭),保存日志而不跟踪堆栈,并使其不可连续性
Appverif –configure 0x2700 –for foo.exe –with ErrorReport=0xA1 Flavor=0x2
验证程序停止选项 - 高级设置
应用程序验证程序具有高级设置(如 Inactivate),你可以根据验证程序停止更改这些设置。
访问验证程序停止选项 - 验证程序停止选项在列出可用选项的对话框中更改。 若要访问验证程序停止选项,请执行以下作:
- 在“测试”窗格中选择测试的名称。
- 在“编辑”菜单上,选择“验证程序停止选项”或右键单击测试,然后选择“验证程序停止选项”。
验证程序停止选项
单击停止代码可以更改每个验证程序停止列出的以下元素(请注意,单击时将显示停止的说明)。
非活动是选中后将停用验证程序停止代码运行的复选框。
严重性确定验证程序停止应如何标记:
- 忽略
- 信息
- 警告
- 错误
错误报告确定希望特定验证程序停止报告/记录的方式:
记录到文件 - 选中后将记录到指定文件的复选框。
日志堆栈跟踪 - 选中的复选框将在可用时记录堆栈跟踪。
无中断 - 调试器中不中断的选项。
异常 - 不带断点和断点的选项
断点 - 不带中断或异常的选项。
杂项提供两个选项
停止一次 - 在测试应用程序时,选中的复选框只会在该错误上停止一次。
不可连续性 - 选中后不允许在不调查的情况下继续的复选框。