应用程序验证工具(Windows 7 和 Windows Server 2008 R2 应用程序质量指南)

受影响的平台:

客户端 - Windows XP、Windows Vista、Windows 7
服务器 - Windows Server 2003、Windows Server 2008、Windows Server 2008 R2

说明

推广和实施应用程序验证工具,将其作为所有开发的质量闸门。 它包括多项改进:

  • 我们提供了额外的检查来解决在使用线程池期间由 Windows 错误报告团队发现的问题。
  • 我们将该包的 32 位和 64 位版本结合起来,以解决 Windows 7 中的更改,包括在 64 位版本的 Windows 下测试 32 位组件的需求,以及总体简化需求。
  • 我们针对下列项提供了额外的检查:多线程应用程序、在 64 位 Windows 上运行 32 位应用程序,以及许多 bug 修复。

这些更改不应对未启用线程检查的用户产生负面影响;那些启用了该检查的用户在发现和诊断现有线程池使用问题方面应该会获得额外的支持。 无论你是否启用线程检查,都将受益于此服务中的其他改进和 bug 修复。

虽然使用此服务时性能会稍有下降,但性能级别应当会保持在可接受的级别,因为它通常不会在零售环境中运行。

使用情况

常规信息

若要交付可靠的 Windows 应用程序,请执行以下操作:

  1. 使用调试程序下的应用程序验证工具以及完整页堆测试以非托管(原生)代码编写的应用程序,然后再将其发布给客户。
  2. 按照应用程序验证工具提供的步骤解决异常情况。
  3. 发布你的应用程序后,定期监视 Windows 错误报告收集的应用程序故障报告。

线程池检查在“基本信息”检查标题下默认启用。 由于这包括在默认设置中,因此用户只需要使用默认设置对其代码运行应用程序验证工具即可利用新的检查。

详细信息

至少应在选择“基本信息”设置的情况下运行应用程序验证工具。 这是 WinLogo 和 WinQual 所必需的。 “基本信息”设置检查以下项:

  • 异常停止详细信息 - 确保应用程序不使用结构化异常处理来隐藏访问冲突
  • 句柄停止详细信息 - 进行测试以确保应用程序未尝试使用无效句柄
  • 堆停止详细信息 - 检查堆中的内存损坏问题
  • 输入/输出停止详细信息 - 监视异步 IO 的执行并执行各种验证
  • 泄漏停止详细信息 - 通过跟踪在卸载 dll 时该 dll 未释放的资源来检测泄漏
  • 锁停止详细信息 - 验证关键部分的正确用法
  • 内存停止详细信息 - 确保正确使用了用于虚拟空间操作的 API(例如 VirtualAlloc、MapViewOfFile)
  • TLS 停止详细信息 - 确保正确使用了线程本地存储 API
  • 线程池停止详细信息 - 确保线程池 API 的正确使用,并在回调后对工作线程状态强制执行一致性检查

如果要从“Vista 前”应用程序迁移你的应用程序,则需要利用“LuaPriv”(也称为 UAC 检查)。 受限用户帐户特权预测器 (LuaPriv) 有两个主要目标:

  • 预测:使用管理特权运行应用程序时,预测当使用较低特权(通常以普通用户身份)运行时应用程序是否将正常运行。 例如,如果应用程序向仅允许管理员访问的文件写入数据,则当以非管理员身份运行时,应用程序将无法向同一文件写入数据。
  • 诊断:使用非管理员特权运行时,识别当前运行可能已存在的潜在问题。 继续前面的示例,如果应用程序尝试向仅允许管理员组成员访问的文件写入数据,则应用程序将收到 ACCESS_DENIED 错误。 如果应用程序无法正常运行,则此操作可能是罪魁祸首。

LuaPriv 识别以下类型的问题:

潜在问题 描述
受限命名空间 在没有命名空间的情况下创建命名的同步对象(事件、信号灯、互斥等)可能会使在某些操作系统上没有特权的情况下运行变得复杂,因为操作系统可能会选择将对象放置在受限的命名空间中。 在受限命名空间(例如全局命名空间)中创建此类对象需要 SeCreateGlobalPrivilege,该特权仅授予给管理员。
如果 LuaPriv 检测到这两个问题,则会标记它们。
硬管理员检查 某些应用程序询问用户的安全令牌,以了解他/她拥有多少特权。 在这些情况下,应用程序可能会根据它认为用户拥有的能力来更改其行为。
LuaPriv 对返回此信息的 API 调用进行标记。
请求特权 在执行需要安全相关特权(例如 SeTcbPrivilege 或 SeSecurityPrivilege)的操作之前,应用程序可能会尝试启用该特权。
LuaPriv 会对启用安全相关特权的尝试进行标记。
缺少特权 如果应用程序尝试启用用户没有的特权,则可能表明该应用程序需要特权,这可能会导致行为差异。
LuaPriv 会对失败的特权请求进行标记。
INI 文件操作 尝试以非管理员用户身份写入到映射的 INI 文件(WritePrivateProfileSection 和类似 API)可能会失败。
LuaPriv 会对此类操作进行标记。
拒绝访问 如果应用程序尝试访问对象(文件、注册表项等),但尝试由于访问权限不足而失败,则应用程序可能应当以比它拥有的特权更多的特权运行。
LuaPriv 会对失败且出现 ACCESS_DENIED 和类似错误的对象打开尝试进行标记。
拒绝 ACE 如果对象在其 DACL 中具有拒绝 ACE,则它会显式拒绝对特定实体的访问。
这不常见,并且会使预测变得困难,因此 LuaPriv 在发现拒绝 ACE 时会对它们进行标记。
访问受限 如果应用程序尝试打开未授予普通用户权限的对象(例如,尝试写入到只能由管理员写入的文件),则该应用程序在以普通用户身份运行时可能无法正常工作。
LuaPriv 会对此类操作进行标记。
MAXIMUM_ALLOWED 如果应用程序打开 MAXIMUM_ALLOWED 的某个对象,则在其他位置将执行对该对象的实际访问检查。 执行此操作的大多数代码无法正常工作,而且在不使用特权的情况下运行时几乎肯定会以不同的方式工作。
因此,LuaPriv 会对 MAXIMUM_ALLOWED 的所有事件进行标记。

 

通常被忽视的问题被捕获到模糊的杂项检查中:

  • 危险 API 停止详细信息
  • 脏堆栈停止详细信息
  • 时间滚动更新

我们添加了一个新的打印验证工具。 此层有助于查找和解决应用程序调用打印子系统时可能导致的问题。 打印验证工具面向打印子系统的两个层,即 PrintAPI 层和 PrintDriver 层。

打印 API 层

打印验证工具会测试程序与 Winspool.drv 和 prntvpt.dll 之间的接口,并测试这些 DLL 的接口。

打印驱动程序层

打印验证程序还会测试核心打印驱动程序(如 UNIDRV.DLL、UNIDRUI.DLL、PSCRIPT5.DLL、PS5UI.DLL 或 MXDWDRV.DLL)与打印驱动程序插件之间的接口。

请注意,其中一些检查仅适用于 Windows 7,并且其他检查在 Windows 7 下会表现得更好。

通常,只有调试版本运行应用程序验证工具,因此性能通常不是问题。 如果使用此检查或任何其他应用程序验证工具检查时导致性能问题,请一次运行一项检查,直到执行完所有需要的检查。

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

通过 Winqual Web 门户监视应用程序的可靠性状态。 此门户显示通过 Windows 错误报告收集的错误报告,因此可以轻松识别最频繁出现的故障。 从“Windows 错误报告:入门”详细了解此信息。 对于此服务,Microsoft 不收费。

若要利用 WinQual,你必须:

  1. 为 WinQual 注册你的公司,这需要一个 VeriSign ID。 可以在开发人员门户中找到有关 WinQual 的 Windows 7 信息,它位于 Windows Vista SP1 \ Windows Server 2008 分组下。 它很快将有自己的 Windows 7 位置。
  2. 将 ISV 应用程序映射到产品名称和 ISV 名称,这会将故障报告链接到公司。 其他 ISV 无法查看你的错误报告。
  3. 使用门户来确定常见问题。 ISV 还可以创建响应,告知客户在发生故障后要采取哪些步骤。 响应系统支持全球 10 多种语言。

另请注意:应用程序验证工具仅针对运行它的代码路径运行良好。 务必将此工具与某个代码覆盖率工具结合使用。

适用于 Windows 的调试工具:

应用程序验证工具:

WinQual: