Windows Installer 最佳做法

本部分枚举一系列链接到 Windows Installer SDK 主文档的提示,以帮助应用程序开发人员、安装作者、IT 专业人员和基础结构开发人员发现使用 Windows Installer 的最佳做法:

更新 Windows Installer 版本。

  • 在 Windows Server 2008 R2 和 Windows 7 上使用 Windows Installer 5.0。 这是随操作系统提供的 Windows Installer 版本。
  • 在 Windows Server 2008、Windows Server 2003(带有服务包 1 (SP1)), Windows Vista(带有服务包 1 (SP1))或 Windows XP(带有服务包 2 (SP2))上使用 Windows Installer 4.5。 有关获取最新 Windows Installer 版本的信息,请参阅 Windows Installer 可再分发组件
  • 在 Windows 2000(带有服务包 3 (SP3))上使用 Windows Installer 3.1。 Windows Installer 版本 3.1 具有帮助更好地进行应用程序服务和修补的功能。
  • 许多重要功能已引入版本 3.0,并列在 Windows Installer 版本 2.0 中不受支持的部分一节。 可以使用 Windows Installer 3.0 及更高版本安装为 Windows Installer 2.0 创建的安装包和更新。 包含 Windows Installer 3.0 使用的新表的修补程序包仍可使用更早版本的 Windows Installer 应用,但不能使用 Windows Installer 3.0 修补功能。 还可以创建显式要求无法由早期版本的 Windows Installer 应用的 Windows Installer 3.0 的修补程序。 如果用户无法更新安装程序版本,请确保应用程序或更新将会与 Windows Installer 的未来更新兼容。
  • 有关较早版本的 Windows Installer 不支持的 Windows Installer 功能的列表,请参阅 Windows Installer 中的新增功能

满足 Windows 徽标认证要求。

  • 即使你不打算将应用程序提交到徽标计划,遵循徽标认证指南也有助于改进 Windows Installer 程序包。 有关徽标要求的概述以及指向特定徽标认证计划的链接,请参阅 Windows Installer 和徽标要求

准备用于本地化的包。

更新 Windows Installer 开发工具和文档。

  • Windows Installer 开发工具不可再分发,你只应使用 Microsoft 提供的这些工具的版本。 这些工具在 Microsoft Windows 软件开发工具包 (SDK) 中的适用于 Windows Installer 开发人员的 Windows SDK 组件中提供。
  • 多个独立软件供应商提供用于创建或修改 Windows Installer 包的工具。 这些工具可以提供一个包创建环境,可能比 Windows Installer SDK 中提供的工具更容易使用。 你可以通过 Windows Installer 信息的其他源中讨论的信息资源了解有关这些工具的详细信息。
  • 对于某些开发人员而言,从文本文件生成包的功能可能更加直观。 Sourceforge.net 上提供的 Windows Installer XML (WiX) 工具集通过 XML 源代码生成 Windows 安装包。
  • MSDN 在线库中发布的 Windows Installer SDK 中的文档更新频率最高。
  • 使用适用于 Windows Vista 或更高版本的 Windows Installer 开发人员的 Windows SDK 组件中提供的最新版本 Msizap.exe(版本 3.1.4000.2726 或更高版本)。 较低版本的 Msizap.exe 可以删除有关已应用于用户计算机上的其他应用程序的所有更新的信息。 如果删除此信息,可能需要删除其他这些应用程序并重新安装才能接收其他更新。
  • 数据库表编辑器 Orca.exe 是用于创建和编辑 Windows Installer 包和合并模块的数据库表编辑器。 它具有基本的 GUI 界面,但支持对 Windows Installer 数据库进行高级编辑。 即使使用另一个应用程序作为主要开发工具,在对包进行故障排除和测试时,你也可以会发现使用 Orca.exe 更方便。
  • 请参阅博客、技术聊天、新闻组、技术文章和网站中提供的当前 Windows Installer 信息的其他 Windows Installer 信息源

如果你决定重新打包旧版安装应用程序,请遵循良好的重新打包做法。

许多应用程序供应商为安装或其产品提供本机 Windows Installer 程序包。 将现有的旧安装应用程序转换为 Windows Installer 程序包的软件称为重新打包工具。 重新打包现有的安装应用程序并不是最佳开发做法。 从一开始就设计利用 Windows Installer 功能的应用程序可以更轻松地安装和服务。 如果你决定使用重新打包软件,则遵照以下做法可以帮助你生成更好的 Windows Installer 程序包。

  • 重新打包工具通过在安装前后拍摄分步系统的照片,将旧安装转换为 Windows Installer 程序包。 在捕获过程中发生的任何注册表更改、文件更改或系统设置都会包含在安装中。 配置用于重新打包安装的计算机的硬件和软件,使其尽可能接近预期用户的系统。 为每个不同的硬件配置创建单独的程序包。 使用干净的分步计算机重新打包。 删除任何不必要的应用程序。 停止所有不必要的进程。 关闭所有非基本系统服务。
  • 在开始处理原始安装之前,请始终复制其副本。 始终处理副本。 在包完成生成之前,切勿停止重新打包程序。 如果重新打包程序损坏了包,你仍将拥有原始包。
  • 请不要将 Microsoft 软件更新重新打包到 Windows Installer 程序包中。 Microsoft 将软件更新(如服务包)发布为自动运行安装的自解压缩文件。 这些更新使用与 Windows Installer 不同的安装程序来替换受保护的 Windows 资源,且无法转换为 Windows Installer 包。 有关如何部署 Windows 服务包的信息,请参阅 Microsoft TechNet 上的服务包部署指南。
  • 请不要使用重新打包工具将 Windows Installer 程序包转换为新包。 Windows Installer 将配置信息添加到系统和应用程序资源中。 当重新打包工具比较安装前后的系统时,重新打包程序将配置信息误解释为应用程序的一部分。 这通常会损害重新打包的应用程序。 改为使用自定义转换来修改现有的 Windows Installer 程序包,或创建新的包。 你可以使用 Msitran.exe 工具创建自定义转换。
  • 请不要使用重新打包工具将多个 Windows Installer 程序包合并到一个包中。 相反,你可以使用 Msistuff.exe 工具来配置 Setup.exe 启动可执行文件,依次安装包。
  • 创建 Windows Installer 包,以便客户可以轻松对其它进行自定义。 Windows Installer 在安装过程中使用的全局变量可以使用公共属性自定义转换进行设置。 为所有可自定义的值提供使用这些属性和实际默认值的文档。 有关获取和设置属性的信息,请参阅使用属性。 有关自定义转换的示例,请参阅自定义转换示例

请不要尝试替换受保护的资源。

Windows Installer 程序包不应在安装或更新期间尝试替换受保护的资源。 Windows Installer 不会删除或替换这些资源,因为 Windows 会阻止替换基本的系统文件、文件夹和注册表项。 保护这些资源可防止应用程序和操作系统出现故障。

  • 在 Windows Server 2008 或 Windows Vista 上运行时,Windows Installer 将跳过受 Windows 资源保护 (WRP) 保护的任何文件或注册表项的安装,安装程序在日志文件中输入警告,并继续安装其余部分,而不会出现错误。 有关信息,请参阅使用 Windows Installer 和 Windows 资源保护
  • WRP 是 Windows 文件保护 (WFP) 的新名称。 WRP 保护注册表项和文件夹以及基本的系统文件。 在 Windows Server 2003、Windows XP 和 Windows 2000 中,当 Windows Installer 遇到受 WFP 保护的文件时,安装程序将请求 WFP 安装该文件。 有关信息,请参阅使用 Windows Installer 和 Windows 资源保护

不依赖于非关键性资源。

由于以下原因,安装或更新不应依赖于非关键性资源的安装。

  • 如果自定义操作依赖于属于用户播发而不是安装的功能的组件,则自定义操作可能会失败。
  • 如果自定义操作依赖于包含正在安装的程序集的组件,则排序在 InstallFinalize 操作之前的自定义操作可能会失败。 在 InstallFinalize 操作完成之前,Windows Installer 不会将程序集提交到全局程序集缓存 (GAC)。

使用 API 检索 Windows Installer 配置信息。

应用程序或更新的安装不应取决于对计算机上保存的 Windows Installer 配置信息的直接访问。 请改用 Windows Installer 应用程序编程接口来检索配置信息。 配置信息的位置和格式由 Windows Installer 服务进行管理,可以更改。

请围绕组件组织应用程序的安装。

Windows Installer 服务安装或删除称为组件的资源集合。 由于组件通常是共享的,因此安装包的作者在指定功能或应用程序的组件时必须遵循规则。

  • 将应用程序组织到组件时,请遵循组件规则,以确保可以安装和删除新组件或组件的新版本,而不会损坏其他应用程序。 你可以按照定义安装程序组件中所述的过程进行操作。
  • 安装程序按组件表中指定的相应组件 ID GUID 跟踪每个组件。 对于 Windows Installer 引用计数机制的操作,组件 ID GUID 是否正确至关重要。 请遵循更改组件代码中的指南。
  • 如果包必须打破组件规则,请注意可能的后果,并确保你的安装永远不会安装这些可能损坏用户系统上的组件的组件。 有关信息,请参阅如果组件规则被破坏,会发生什么?
  • 请注意 Windows Installer 在替换现有文件时如何应用文件版本控制规则。 Windows Installer 首先确定组件的密钥文件是否已安装,然后再尝试安装组件的任何文件。 如果安装程序找到与安装在目标位置的组件密钥文件同名的文件,则会比较这两个密钥文件的版本、日期和语言,并使用文件版本控制规则来确定是否安装程序包提供的组件。 如果安装程序确定它需要根据密钥文件替换组件,它会在每个已安装的文件上使用文件版本控制规则来确定是否替换该文件。

减小大型 Windows Installer 程序包的大小。

非常大的 Windows 包会占用系统资源,用户可能很难安装。 最好通过以下方法减小非常大的 Windows Installer 程序包的大小。

  • 压缩安装中的文件并将其存储在 cabinet (.cab) 文件中。 安装程序允许将 .cab 文件作为单独的外部文件存储,或作为 MSI 包本身的数据流存储。 有关信息,请参阅使用 Cabinet 和压缩源
  • 使用减小 .msi 文件的大小中讨论的选项之一删除 .msi 文件中浪费的存储空间。
  • 如果 Windows Installer 包中包含的文件数超过 32767 个,则必须更改数据库的架构。 有关信息,请参阅创建大型程序包

如果使用自定义操作,请遵循良好的自定义操作做法。

Windows Installer 有许多用于安装和维护应用程序的内置标准操作。 开发人员应尽可能尝试依赖标准操作,而不是创建自己的自定义操作。 但是,在某些情况下,安装包的开发人员发现有必要编写自定义操作。

如果使用程序集,请遵循良好的程序集做法

如果你的程序包使用软件程序集,请遵循将程序集添加到包更新程序集以及安装和删除程序集的指南。

请不要交付并发安装。

并发安装(也称为嵌套安装)会在当前运行的安装过程中安装另一个 Windows Installer 包。 使用并发安装不是好的做法,因为它们对客户来说很难提供服务。 修补和升级可能不适用于并发安装。 使用并发安装的建议替代方法是改用安装应用程序和外部 UI 处理程序按顺序安装多个 Windows Installer 包。

有关使用外部 UI 处理程序的详细信息,请参阅使用 MsiSetExternalUI 监视安装。 有关使用基于记录的外部处理程序的详细信息,请参阅使用 MsiSetExternalUIRecord 监视安装

并发安装有时在受控的公司环境中用于安装不适合公众的应用程序。 如果决定使用并发安装,请遵循以下指南。

  • 请不要使用并发安装来安装或更新发货产品。
  • 并发安装不应共享组件。
  • 管理安装不应包含并发安装。
  • 集成的 ProgressBars 不应与并发安装一起使用。
  • 要播发的资源不应通过并发安装来安装。
  • 执行应用程序并发安装的包还应在卸载父级产品时卸载并发应用程序。 嵌套安装位于控制面板的“添加/删除程序”中的父级产品的上下文下。

使包的名称和包代码保持一致。

可以为 .msi 文件提供任何可以帮助用户标识包的名称,但是如果没有更改产品代码,就不应该更改名称。

  • 为 .msi 文件提供用户友好名称,使用户能够标识 Windows Installer 包的内容。
  • 此产品代码是应用程序的主体标识,每当应用程序有全面的更新时,都必须更改。 有关信息,请参阅 ProductCode更改产品代码。 更改应用程序的 .msi 文件的名称被认为是一项全面的更改,并且始终需要相应地产品代码更改才能保持一致性。
  • 程序包代码是安装程序用于搜索和验证给定安装的正确包的主要标识符。 任何两个不相同的 .msi 文件都不应具有相同的包代码。 如果在不更改包代码的情况下更改包,则在安装程序仍可访问这两个包的情况下,它可能不会使用较新的包。 包代码存储在摘要信息流的修订号摘要属性中。
  • 请注意,产品代码和包代码 GUID 中的字母都必须大写。

请不要使用 SelfReg 和 TypeLib 表。

  • 强烈建议安装包作者不要使用自注册和 SelfReg 表。 相反,它们应通过创建注册表表组中的一个或多个表来注册模块。 Windows Installer 的许多好处都因自注册而丢失,因为自注册例程往往会隐藏关键配置信息。 有关避免自注册的原因的列表,请参阅 SelfReg 表
  • 强烈建议安装包作者不要使用 TypeLib 表。 使用注册表表注册类型库,而不是使用 TypeLib 表。 如果使用 TypeLib 表的安装失败并且必须回滚,则回滚操作可能不会将计算机还原到回滚之前存在的相同状态。

提供不使用用户界面安装的选项。

管理员通常更喜欢在公司内部署应用程序,而无需用户交互。 最好的做法是让应用程序提供用户界面级别为 None 的安装选项。

  • 公共属性用于配置信息。 管理员可以在命令行上提供此信息。
  • 不要求安装依赖于从用户与对话框的交互中收集的信息。 此信息在无提示安装过程中不可用。
  • 请不要在无提示安装过程中自动重启用户的计算机。
  • 管理员可以在使用命令行选项 "/q" 安装时设置用户界面级别。 还可以使用对 MsiSetInternalUI 的调用以编程方式设置用户界面级别。

请避免使用 AlwaysInstallElevated 策略。

如果未设置 AlwaysInstallElevated 策略,则管理员未分发的应用程序将使用用户的权限进行安装,并且只有托管应用程序才能获得提升的权限。 设置此策略会指示 Windows Installer 在系统上安装应用程序时使用系统权限。 此方法可能会使计算机面临安全风险,因为设置此策略时,非管理员用户可以使用提升的权限运行安装,并访问计算机上的安全位置。 使用提升的权限为非管理员安装程序包修补每个用户的托管应用程序时,最好的做法是使用另一种方法,而不是 AlwaysInstallElevated 策略。

启用 DisableMedia 策略以限制未经授权的安装。

DisableMedia 策略可阻止未经授权的应用程序安装。 启用此策略后,运行一个产品的维护安装的用户和管理员将被阻止使用“浏览”对话框浏览媒体源,例如 CD-ROM,以获取其他可安装产品的源。 无论是否使用提升的权限完成安装,浏览其他产品都会被阻止。 如果用户拥有正确标记的媒体源,用户仍可以从媒体重新安装产品。

使原始的包源文件安全且可供用户使用。

在某些情况下,可能需要 Windows Installer 程序包的原始源才能按需安装、修复或更新应用程序。 如果安装程序找不到可用的源,则用户需要提供媒体或转到包含所需源的网络位置。 最好的做法是确保安装程序具有所需的源,而无需提示用户。

  • 使用数字签名和外部 Cabinet 文件来确保安装程序正在使用的原始源是安全的。 存储在公共位置的未压缩源映像不安全。
  • SOURCELIST 属性中包含应用程序安装包的网络或 URL 源路径的完整列表。
  • 将分布式文件系统 (DFS) 共享用于源路径。
  • 使用 Windows Installer API 检索和修改 Windows Installer 应用程序和修补程序的源列表信息。 有关信息,请参阅管理安装源
  • 使用 Installer 对象产品对象修补对象的方法和属性来检索和修改 Windows Installer 应用程序和修补程序的源列表信息。
  • 为了最大程度地降低修补程序要求访问原始源的可能性,请遵守阻止修补程序要求访问原始安装源中列出的要点。
  • 将程序包源文件存储在不是系统的临时文件夹的位置。 存储在临时文件夹中的 Windows Installer 源文件对用户不可用。

排查部署问题时,在用户计算机上启用详细日志记录。

Windows Installer 日志记录包括可在用户计算机上启用的详细日志记录选项。 尝试排查 Windows Installer 包部署问题时,详细日志中的信息非常有用。

  • 你可以通过使用可以使用命令行选项MsiLogging 属性、日志记录策略MsiEnableLogEnableLog 方法在用户的计算机上启用详细日志记录。
  • 用于解释 Windows Installer 日志文件的非常有用的资源是 Wilogutl.exe。 此工具有助于分析日志文件,并显示日志文件中发现的错误的建议解决方案。
  • 详细日志记录选项应仅用于故障排除目的,不应保留,因为它可能会对系统性能和磁盘空间产生不利影响。 每次在控制面板中使用“添加/删除程序”工具时,都会创建一个新文件。

卸载会使用户的计算机处于干净状态。

应用程序删除与安装一样重要。 卸载 Windows Installer 程序包后,不应在用户的计算机上留下任何无用部分。

  • 如果在运行卸载后,应从用户计算机中删除的文件仍保持安装,则出于删除闲置文件中描述的一个或多个原因,安装程序可能无法删除包含该文件的组件。
  • 如果必须注册应用程序,请创建程序包,以在卸载应用程序时删除注册表信息。 有关信息,请参阅在安装或删除组件时添加或删除注册表项。 如果未注册应用程序,则应用程序不会列在控制面板中的“添加或删除程序”功能中,并且无法使用 Windows Installer 进行管理。
  • 要在控制面板的“添加或删除程序”功能中隐藏应用程序,并且仍然能够使用 Windows Installer 管理应用程序,请遵循添加和删除应用程序和在注册表中不留痕迹中所述的指南。
  • 自定义操作应该根据需要在卸载时运行或不运行。 不同的自定义操作可能需要在安装和卸载时运行。
  • 特定于用户的自定义信息可以存储在计算机上的文本文件中。 这有一个优点,即在卸载应用程序时,即使此自定义项的用户当前未登录,也可以删除该文件。

针对每个用户和每台计算机安装部署测试包。

最好的做法是让客户决定是否在每台计算机或每个用户的安装上下文中部署用于安装的包。

  • 请考虑应用程序在开发过程中是仅对特定用户可用还是对计算机的所有用户可用。
  • 测试包是否适用于每个用户的安装和每台计算机的安装上下文。
  • 使包易于自定义,并让客户决定是按每个用户还是每台计算机部署它。

在交付应用程序之前计划和测试服务策略。

在首次部署应用程序之前,你应该决定如何为应用程序提供服务。

  • 请考虑你希望在将来为应用程序服务时使用的更新类型。 Windows Installer 提供三种类型的更新:小型更新次要升级主要升级。 它们之间的差别见修补和升级主题所述。
  • 在交付应用程序之前,请在使用每个更新类型进行服务后,测试它是否按预期工作。

减少对原始源的更新依赖项。

如果需要原始源文件来更新应用程序,这会使应用程序服务更加困难。 以下方法有助于减少对原始源的更新依赖性。

请不要分发无法提供服务的合并模块。

如果合并模块的所有者和应用程序的所有者不同,则应用程序不应依赖于合并模块安装组件。 这可能导致难以为应用程序提供服务,因为两个所有者需要协调才能更新应用程序或模块。 在不知道使用合并模块的所有应用程序的情况下,应用程序的所有者无法更新合并模块,否则将面临更新可能与其他应用程序不兼容的风险。 合并模块的所有者没有更新已经安装了合并模块的 Windows Installer 程序包的直接方法。

  • 请考虑将所需的组件作为另一个 Windows Installer 安装提供给用户。

请避免修补管理安装。

在网络上提供应用程序的原始 Windows Installer 程序包的管理安装,使工作组成员能够安装该应用程序。 然后,此管理映像的用户应将更新应用于位于其计算机上的应用程序的本地实例。 这样,用户便能够与管理映像保持同步。 出于以下原因,不建议对管理安装应用更新。

  • 与下载修补程序相比,用户获取更新所需的下载大小和延迟会增加。 整个更新的 Windows Installer 程序包和源文件必须下载、重新缓存和重新安装。
  • 用户在重新缓存和重新安装应用程序之前,无法从更新的管理安装中按需安装并修复应用程序。
  • 将修补程序应用到管理安装会从程序包中删除数字签名。 管理员必须重新对程序包签名。 有关使用数字签名的详细信息,请参阅数字签名和 Windows Installer
  • 许多二进制修补程序面向应用程序的 RTM 映像,并且需要先前的文件版本。 从更新的管理安装中安装的应用程序的本地实例可能不适用于其他更新。 许多二进制修补应用程序可能会失败。
  • 将修补程序应用于管理安装会更新源文件和 .msi 文件,但不会使用有关更新的信息标记网络映像。 用户无法确定它们从管理安装中收到哪些更新。 这使得无法将应用于用户端的更新与已经应用于管理映像端的更新进行排序。
  • 应用于管理安装的修补程序不是不可卸载的修补程序。 这可以防止用户计算机上缓存的包代码与管理安装上的包代码不同。 如果用户计算机上缓存的包代码与管理安装上的包代码不同,请从管理安装中重新安装应用程序,然后修补客户端计算机。
  • 如果决定通过修补管理映像来应用小型更新,请按照以下主题中所述的指南操作:通过修补管理映像来应用小型更新

注册更新以使用提升的权限运行。

从 Windows Installer 3.0 开始,可以在修补程序被注册为具有提升权限后,将修补程序应用到已安装在每个用户托管的上下文中的应用程序。 使用版本低于 3.0 的 Windows Installer,无法对安装在每个用户的托管上下文中的应用程序应用修补程序。

使用 MsiPatchSequence 表对修补程序进行排序。

在包中包含 MsiPatchSequence 表,并添加修补程序先后顺序信息。 从 Windows Installer 版本 3.0 开始,安装程序在安装多个修补程序时,可以使用 MsiPatchSequence 表以确定最佳修补应用程序顺序。 使用 Windows Installer 版本 3.0 中的修补程序先后顺序白皮书中描述的指南来定义修补程序系列。

  • 如果可行,请将所有修补程序指定为属于单个修补程序系列。 在许多情况下,单个修补程序系列提供足够的灵活性来对修补程序进行排序。 使用多个修补程序系列时,创作的复杂性会增加。 为修补程序系列分配有意义的名称,并在该修补程序系列中分配随时间增加的顺序值。 按照多个修补示例以其发布顺序应用修补程序。
  • 使用 Patchwiz.dll 中的 PatchSequence 表生成 MsiPatchSequence 表中的信息。 随 Windows Installer 3.0 一起发布的 PATCHWIZ.DLL 版本可以自动生成修补程序先后顺序信息。 有关如何添加新修补程序的详细信息,请参阅生成修补程序顺序信息。 有关修补先后顺序方案的详细信息,请参阅白皮书:Windows Installer 版本 3.0 中的修补先后顺序

充分测试安装包。

测试 Windows Installer 程序包是否正确安装、修复和删除。 你可以将测试过程划分为以下部分。

  • 安装测试 - 使用应用程序功能的所有可能组合测试安装。 测试所有类型的安装,包括管理安装回滚安装按需安装。 尝试所有可能的安装方法,包括单击 .msi 文件、命令行选项以及从控制面板进行安装。 测试包是否可以由用户在所有可能的特权上下文中安装。 在使用所有可能的方法部署包之后,尝试安装它。 为每个测试启用 Windows Installer 日志记录,并解决在安装程序日志和事件日志中发现的所有错误。
  • 用户界面测试 - 在安装时使用所有可能的用户界面级别测试包。 在没有用户界面和通过用户界面提供的所有信息的情况下测试安装的包。 确保用户界面的辅助功能,并确保用户界面在不同的屏幕分辨率和字号下按预期工作。
  • 服务和修复测试 - 测试包是否可以处理小型更新次要升级主要升级提供的修补和升级。 在部署包之前,请编写每种类型的试用版更新,并尝试将其应用于原始包。
  • 卸载测试 - 验证当软件包被删除时,它不会在用户的计算机上留下无用的部分,并且仅删除属于该包的信息。 在卸载包后重启测试计算器,并验证常见系统工具和其他标准应用程序的完整性。 测试包是否可以在所有可能的特权上下文中被用户删除。 测试删除包的所有方法,单击 .msi 文件,试用命令行选项,然后尝试从控制面板中删除包。 为每个测试启用 Windows Installer 日志记录,并解决在安装程序日志和事件日志中发现的所有错误。
  • 产品功能测试 - 确保应用程序在安装、修复或删除包后按预期运行。

在部署新的或修订的安装包之前修复所有的验证错误。

首次尝试安装包之前,请在新的或修订的 Windows Installer 程序包上运行包验证。 验证将检查 Windows Installer 数据库的创作错误。 尝试安装未通过验证的包可能会损坏用户的系统。

  • 可以使用 Orca.exeMsival2.exe 来验证包。 这两个工具都随 Windows SDK 一起提供。 第三方供应商还可以将 ICE 验证系统合并到其创作环境。
  • 你可以使用随 SDK 一起提供的 .cub 文件中包含的标准的内部一致性估算器 - ICE 集,也可以通过生成 ICE 并将其添加到 .cub 文件来自定义验证。
  • 你可以使用 Evalcom2.dll 为安装包和合并模块实施验证自动化

创建安全安装。

在开发包时遵循以下指南,以帮助在安装过程中维护安全环境。

使用 PMSIHANDLE 而不是 HANDLE

PMSIHANDLE 类型变量在 msi.h 中定义。 建议应用程序使用 PMSIHANDLE 类型,因为安装程序会在 PMSIHANDLE 对象超出范围时关闭它们,而应用程序必须通过调用 MsiCloseHandle 来关闭 MSIHANDLE 对象。 PMSIHandleMSIHANDLE 提供类型转换运算符,以实现 API 签名兼容性。

例如,如果你使用如下所示的代码:

MSIHANDLE hRec = MsiCreateRecord(3);

请将其更改为:

PMSIHANDLE hRec = MsiCreateRecord(3);