应用程序验证工具 - 测试应用程序

应用程序验证程序 (AppVerifier) 是一种适用于非托管代码的运行时验证工具,可帮助查找难以使用常规应用程序测试技术识别的微妙编程错误、安全问题和有限的用户帐户特权问题。

若要提供可靠的 Windows 应用程序,需要:

  1. 测试使用非托管 (本机) 代码编写的应用程序,在调试器下使用应用程序验证程序和整页堆,然后再将其发布给客户。
  2. 按照应用程序验证程序提供的步骤解决错误情况。
  3. 发布应用程序后,定期监视收集的应用程序故障报告,例如Windows 错误报告(如果可用)。

默认情况下,在“基本信息”检查标题下启用线程池检查。 由于此设置包含在默认设置中,因此用户只需使用默认设置在其代码上运行应用程序验证程序,即可利用这些检查和其他重要检查。

配置应用程序验证程序

调试器设置

正在验证的应用程序应在用户模式调试器下运行,或者系统应在内核调试器下运行,因为在发生错误时,它会中断到调试器中。 有关调试器的详细信息,请参阅 应用程序验证程序 - 调试应用程序验证程序停止

设置

无法为正在运行的进程启用应用程序验证程序。 因此,需要按如下所述进行设置,然后启动应用程序。 这些设置是永久性的,直到显式删除。 因此,无论启动应用程序多少次,它都会在启用 AppVerifier 的情况下启动,直到删除设置。

使用应用程序验证程序基础知识测试

以下方案演示了建议的命令行和用户界面选项。 这些应在执行代码的所有测试期间运行,以确保完全覆盖。 这些方案的预期是,应用程序不会中断调试器,并且所有测试都以与在未启用 AppVerifier 的情况下运行时相同的通过率通过。

为要测试的应用程序启用验证程序 () 。 从命令行: appverif /verify MyApp.exe

在用户界面中:右键单击“应用程序”区域并选择“添加应用程序”,添加应用程序。 从“测试”区域选择“基本信息”。 单击“保存”按钮。

注意:

/verify 将启用基础知识测试

如果要测试 DLL,则必须为执行 DLL 的测试可执行文件启用应用程序验证程序。

单独运行验证层。 例如,在一个会话中启用所有基本信息,在另一个会话中启用所有 LuaPriv 检查。

运行执行应用程序的所有测试。

分析遇到的任何调试器中断 () 。 如果发生中断,则需要了解它并修复它。 注意:帮助内容提供有关中断以及如何调查它们的详细信息。

完成后,删除所有设置。 从命令行: appverif /n MyApp.exe

在用户界面中,右键单击“应用程序”区域并选择“删除应用程序”来删除应用程序。 然后单击“保存”按钮。

堆损坏

Windows 系统上近 10% 的应用程序崩溃是由于堆损坏造成的。 这些崩溃几乎不可能在事后进行调试。 避免这些问题的最佳方法是使用应用程序验证器中的页面堆功能进行测试。 页面堆有两种样式:“Full”和“Light”。默认为 Full;它将强制调试器在检测到损坏时立即停止。 此功能必须在调试器下运行。 但是,它也是最需要资源。 如果用户遇到计时问题,并且已在“完整”页面堆下运行方案,则将其设置为“浅色”可能会解决这些问题。 此外,精简页面堆在进程退出之前不会崩溃。 它确实为分配提供堆栈跟踪,但与利用其完整对应项相比,诊断所需的时间要长得多。

使用 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

为具有 X.DebugLevel 和 Y.DebugLevel 属性的目标test.exe启用两个名为 X 和 Y 的层:

appverif –enable X Y –for test.exe –with X.DebugLevel=1 Y.DebugLevel=2

若要禁用在应用程序上运行的所有检查,请执行以下操作:

appverif -disable * -for notepad.exe

OR

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 设置为 * 以指定应禁用所有目标。

属性是特定于命令行中提到的 LAYER 的属性名称。 例如,“句柄”层将跟踪作为属性。

VALUE 是 属性的值。 值的类型取决于与 属性关联的类型,并且将强制实施该类型。 目前支持的类型为:布尔 (true/false) 、C) 表示法中的整数 (decimal/octal/hex、包含 \0\0') 的字符串和多字符串 (\0’ between strings and being terminated by 。 如果未指定 VALUE,则表示用户想要删除该属性,并将行为还原为属性的默认值。

STOP 是要配置的验证程序停止问题的 C 表示法 (十进制数或十六进制数) 。 停止代码必须是唯一的 (任何两个层都不能使用相同的停止代码,因此工具本身将确定停止点所属的层)

STOPROPERTY 是验证程序停止可接受的属性名称。 如果未指定值,则假定必须删除 属性。 允许的停靠点属性 (请参阅下面的配置验证程序停止,以获取更多详细信息) :

  • ErrorReport
  • 严重性
  • 种类

属性可以选择由它们所属的层进行限定。 但是,如果命令行仅启用一个层,则不需要这样做。 例如,若要为具有属性 X.DebugLevel 和 Y.DebugLevel 的目标test.exe启用两个名为 X 和 Y 的层,命令为:

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启用故障注入。 但是,可以使用命令行来配置要启用的故障注入类型。 例如,如果要将错误作为 2% 注入注册表或文件 API,请使用命令行:

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错误。

对于 Flavor ,值可以是以下值的组合。

0x00000002非连续停止。

0x00000010此停止仅显示一次。 在测试运行中的以下时间,它将被忽略。

例如,禁用停止0x2700,0x2701foo.exe

Appverif –configure 0x2700 0x2701 –for foo.exe –with ErrorReport=0

将停止代码0x2700配置为进入调试器, (默认关闭) ,保存没有堆栈跟踪的日志,并使其不可连续性

Appverif –configure 0x2700 –for foo.exe –with ErrorReport=0xA1 Flavor=0x2

验证程序停止选项 - 高级设置

应用程序验证程序具有高级设置,例如“停用”,你可以根据验证程序停止更改这些设置。

访问验证程序停止选项 - 验证程序停止选项在列出可用选项的对话框中发生更改。 若要访问验证程序停止选项,请执行以下操作:

  1. 在“测试”窗格中选择测试的名称。
  2. 在“编辑”菜单上,选择“验证程序停止选项”或右键单击测试并选择“验证程序停止选项”。

验证程序停止选项

可以通过单击停止代码更改每个验证程序停止列出的以下元素, (注意单击) 时将显示停止的说明。

“非活动”是一个复选框,选中此选项后,验证程序将停止运行代码。

严重性确定应如何标记验证程序停止:

  • 忽略
  • 信息
  • 警告
  • 错误

错误报告确定你希望如何报告/记录特定验证程序停止:

记录到文件 - 选中后将记录到指定文件的复选框。

日志堆栈跟踪 - 选中该复选框后,将在堆栈跟踪可用时记录这些跟踪。

无中断 - 不中断调试器的选项。

异常 - 选项以及没有断点和断点

断点 - 一个选项,不带中断或异常。

杂项提供两个选项

停止一次 - 在测试应用程序时,如果选中该复选框,该复选框将仅针对该错误停止一次。

不连续 - 选中此选项后,将不允许在不进行调查的情况下继续。

另请参阅

应用程序验证程序 - 概述

应用程序验证工具 - 功能

应用程序验证工具 - 应用程序验证工具中的测试

应用程序验证工具 - 停止代码和定义

应用程序验证工具 - 调试应用程序验证工具停止

应用程序验证工具 - 常见问题解答