65.9K
CodeProject 正在变化。 阅读更多。
Home

自解压安装程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (19投票s)

2008年10月19日

CPOL

14分钟阅读

viewsIcon

124831

downloadIcon

11238

创建一个自解压文件,该文件可以启动多个设置

sfxui.PNG

引言

我最近遇到了一个问题,需要一个自解压安装程序,允许客户下载一个巨大的文件,以便他们可以从各种安装程序或相关文档中进行选择,例如自述文件或发行说明。考虑一个公司,它提供由不同组件组成的产品套件,例如服务器安装、客户端安装、管理安装和命令行工具安装。如果每个组件都有一个单独的安装程序或 MSI 文件供客户下载,这对客户来说很快就会变得很麻烦。将每个组件的所有相关安装程序合并到一个大型自解压安装程序中,并提供允许选择单个组件的用户界面,这将是解决此问题的理想方案。

要求

我为解决此问题提出了以下要求

  • 单个安装程序应以压缩格式存储在自解压安装程序中。
  • 压缩格式应为标准格式。
  • 自解压安装程序应在 Windows 2000 及更高操作系统版本上运行,并且应完全采用 UNICODE。
  • 要提取的单个安装程序应按需提取,而不是在程序启动时提取所有嵌入的安装程序。这样,用户硬盘上只需要最小的临时存储空间,并且程序启动速度尽可能快。
  • 每个安装程序组件都应可以通过执行一个可以指定其命令行和可执行文件的程序来启动,或者通过设置组件的文件扩展名进行 ShellExecute。MSI 文件应通过 MSI API 启动,以便 MSI 的用户界面能够被父化到自解压安装程序的窗口。这样,MSI 安装程序在自解压安装程序中的集成度会更高。
  • 构成自解压安装程序的程序应可重用。必须有一种便捷的方法来创建一个自定义的自解压安装程序,使用一个充当自解压安装程序编辑器程序的程序。

解决方案概览

作为压缩格式,我选择了 zip 格式。使用 zip 格式存在一些限制,我将在下面概述。在创建自解压安装程序时,一个包含构成安装的所有文件的 zip 文件将被附加到一个存根文件 (sfx.exe) 之后。该存根将在运行时立即将少量文件提取到临时目录中,然后启动一个子进程 (setupui.exe),该子进程实现用户界面,您可以在文章顶部的截图中看到。自解压安装程序的创建是通过项目的一部分 sfxmaker.exe 程序完成的。使用 sfxmaker.exe,您可以指定哪些文件进入自解压安装程序,以及在运行时向用户提供哪些自解压安装程序的组件。您还可以为自解压安装程序添加品牌信息,以便自解压安装程序的版本信息包含您的公司和产品名称。此外,还可以使用 sfxmaker 进行多种本地化操作,例如自解压安装程序用户界面的标签和按钮上的文本。

对于要安装的每个组件,您可以指定一个自定义图标,该图标将出现在自解压安装程序的列表控件中,位于组件的描述旁边。要实现这一点,这些图标文件必须添加到项目中,并在自解压安装程序启动时提取,以便立即显示。约定是,所有在自解压安装程序启动时需要提取的文件都以“setupui”开头,因此这些图标文件的名称也必须以“setupui”开头。一些在自解压安装程序启动时需要提取的文件具有预定义的名称:如果存在名为 setupui.bmp 的文件,它将显示在自解压安装程序用户界面上,就像上面截图中的气泡位图一样。如果自解压安装程序包中包含名为 setupui.ico 的文件,它将被用作自解压安装程序的图标,在应用程序之间 Alt-Tab 时使用,因此最好在 sfxmaker 中将您的产品图标文件添加为 setupui.ico 到安装程序包中。如果自解压安装程序包中包含名为 setupui.avi 的文件,它将在启动 MSI 安装程序之外的设置程序时显示在进度对话框中,除非该设置是 MSI 安装程序。

Sfxmaker.exe 是一个基于文档视图模型的 MFC 应用程序,它处理以 sfx 文件扩展名命名的文档。由 sfxmaker.exe 创建的这样一个 sfx 文档准确地描述了一个自解压安装程序二进制文件,并且其格式类似于 Windows INI 文件,但采用 UNICODE 格式 (UTF-16)。这使得 SFX 文件 human readable,并且非常适合源代码控制系统。在创建自解压安装程序包时,此 SFX 文档文件将作为 setupui.ini 添加到 zip 文件中,setupui.exe 可以在运行时从该文件中提取所有相关信息。

观察安装程序的工作原理

为了了解这样的自解压安装程序包是如何工作的,请下载 自解压安装程序演示,解压缩并执行它。此演示展示了虚构的 foobar 应用程序套件,其中显示了可在列表中安装或启动的各种组件。前两个组件启动 foobar 服务器和客户端的 MSI 文件。这两个组件显示了 MSI 安装程序的特殊处理,因为自解压安装程序窗口充当 MSI 安装程序窗口的父窗口。现在,启动第三个安装程序,即 foobar 工具安装程序。此安装程序也是基于 MSI 的,但它通过 msiexec 使用特殊命令行启动。请注意,在这种情况下,自解压安装程序窗口和 MSI 用户界面之间没有父子关系,并且安装程序在运行时显示进度对话框。如前所述,您可以指定一个 setupui.avi 文件来覆盖此进度对话框中相对枯燥的动画。第四个组件启动一个可执行文件,演示了如何添加任意 EXE 文件以从您的自解压安装程序包中执行。请注意,在这种情况下您也会看到进度对话框。

最后两个条目允许用户启动包含发行说明的 PDF 文件和 readme 文本文件。对于这两个组件,显示在列表控件中的图标是从关联的应用程序(大多数情况下是 Acrobat Reader 和 Notepad)中提取的。在运行时提取关联的图标可帮助您显示 Acrobat 图标,而无需将其添加到安装程序包中,这会违反 Adobe 的版权。如果有一个文件没有与要 ShellExecute 的文件关联(如 readme 文件或 PDF 文件所做的),那么设置组件的列表控件条目将没有可见图标。

运行 sfxmaker

在这一段中,我将展示如何从现有源文件重新创建自解压安装程序演示。这样,您将对如何为您的产品创建自己的自解压安装程序有一个大致的了解。首先,下载 自解压安装程序的演示项目,并将其目录结构保留,解压缩到驱动器 c:\ 的根目录。构成此演示项目的文件现在应该都在 c:\sfxdemo 目录中。您会看到该目录包含 foobar 客户端、服务器和工具安装的各个 MSI 文件。您还将看到几个用于各个安装程序的 *.ico 文件,以及 readme.txtrelnote.pdf 文件。现在,将 项目源代码 下载到一个空的硬盘目录中,找到包含 sfxmaker.exe 文件的 release 目录,然后启动它。sfxmaker.exe 的用户界面将是

现在,在 sfxmaker 中打开文件 c:\sfxdemo\sfxdemo.sfx,并注意所有用户界面元素是如何被填充的。

  • 标签“公司名称”包含您公司的名称,并在最终的自解压安装程序的版本信息资源中显示。
  • 标签“产品名称”包含您的产品名称,并在最终的自解压安装程序的版本信息资源中显示。
  • 标签“安装组件”下方的列表控件包含安装组件的信息,这些信息按它们在自解压安装程序的列表控件中出现的顺序排列。您可以使用列表控件右侧的按钮移动单个项目,或添加和删除新项目。通过双击项目,您可以更改每个项目的数值。这将调用一个对话框,您可以在其中更改组件的各个参数。
  • 标签“文件”下方的列表框包含所有将被压缩到 zip 文件中的文件,该 zip 文件将被附加到存根以创建自解压安装程序。使用此列表框右侧的按钮添加或删除文件。列表框项目的顺序无关紧要。
  • 在标签“标题文本”旁边指定的文本是显示在最终自解压安装程序的组件列表控件上方的标签中的文本。
  • 在标签“窗口标题”旁边指定的文本是显示在最终自解压安装程序的窗口标题栏中的文本。
  • 在标签“安装按钮文本”旁边指定的文本是显示在最终自解压安装程序中启动安装的按钮上的文本。
  • 在标签“退出按钮文本”旁边指定的文本是显示在最终自解压安装程序中退出按钮上的文本。
  • 标有“Vista 执行级别”的组合框指定最终自解压安装程序在 Windows Vista 上运行时所需的执行级别。

现在,点击标有“创建 SFX”的按钮。它会提示您输入最终自解压安装程序的名称和位置。选择您喜欢的名称和位置,然后点击“确定”。这将需要几秒钟,然后自解压安装程序就会为您创建好。

添加和更新组件

如果您在 sfxmaker 中添加新组件或更新现有组件,将会出现一个如下所示的对话框。

您可以在此处为每个组件指定的项目如下:

  • 描述:这是在最终自解压安装程序的列表控件中显示的组件文本。
  • 命令行:这是一个可选的组件命令行,当在最终自解压安装程序中按下组件的安装按钮或双击该组件时执行。
  • 应用程序:在这里,您可以指定要执行的文件的应用程序路径,以及命令行。
  • 要解压的文件:这是文件在自解压安装程序的 zip 文件中的名称。如果在最终自解压安装程序中按下组件的安装按钮或双击组件,则此文件将被提取到临时目录中,然后可以选择性地启动命令行,或者执行该文件。
  • 图标文件:这是将在最终自解压安装程序用户界面中显示在组件文本旁边的图标文件。如果此值为空,则图标将在运行时从解压文件的扩展名确定。如果您在此处指定图标文件,请确保其名称以“setupui”开头。
  • 文本:这是当选择组件时,在最终自解压安装程序用户界面中的列表控件下方显示的文本。

对于“应用程序”和“命令行”项目,您可以指定包含环境变量的文本。它们将在运行时由自解压安装程序解析。您可以使用特殊环境变量 CURRENTDIRECTORY。此环境变量在运行时会展开为自解压安装程序解压缩文件的临时目录。查看演示项目中的“Foobar Tools 1.0”安装程序如何使用此变量,以便 msiexec.exe 找到 MSI 文件。确保为每个组件的“要解压的文件”在“文件”列表框中添加一个对应的文件名。还要确保将每个图标文件添加到“文件”列表框中。

Using the Code

使用 Visual Studio 2005 和集成的 Vista SDK 或 Server 2008 SDK 来编译项目。纯粹的 Visual Studio 2005 安装将不起作用,因为出于我无法想象的原因,Visual Studio 2005 缺少 msi.dll 的导入库 msi.lib。此外,我在我的代码中大量使用了 PREfast __analysis_assert 语句,以便使其 PREfast-clean。您也可以使用 Visual Studio 2008,它会将解决方案和项目文件为您转换为 Visual Studio 2008 格式。对于这两种开发环境,您都需要包含 MFC 的版本,因此 express 版本是不够的。为了编译项目文件,首先将本文的源代码递归地解压到一个空的硬盘目录中。在项目的 sfx 目录中,创建一个名为 zlib123 的子目录,该子目录应与 includelibmcsetupuisfxmakersfx zlibstatsfxcommn 子目录并行。这是因为您还需要最新版本的 zlib 库,版本 1.2.3。在此目录中 下载库的副本。再次保留目录结构解压缩 zlib 文件到该目录。现在,您应该能够编译整个项目了。

限制

当前实现有三个主要限制,您需要自行判断它们是否对您是问题。

  • 嵌入自解压安装程序中的文件名最好只包含 7 位 ASCII 字符。虽然整个项目都是 UNICODE 的,但 zip 存档中的文件名不是 UNICODE 的。因此,为防止任何问题,请对文件名使用 7 位 ASCII 字符。
  • 要添加到项目中的文件总数不得超过 2 GB。这也是 zip 格式的一个限制。
  • 目前,最终自解压安装程序的 zip 文件中嵌入的所有文件都包含在 zip 文件的根目录中。这样,添加到项目的所有文件都必须具有唯一名称。

提取所有文件

使用命令行参数 -e-x,您可以将自解压安装程序的内容提取到一个目录中。仅指定 -e 作为命令行参数将显示一个目录选择对话框,您可以使用它来选择或创建目录,所有文件都应该提取到该目录中。如果您使用 -e=targetdirectory -x=targetdirectory 作为命令行参数,所有文件都将提取到目标目录,而不会显示目录选择对话框。因此,例如,如果您指定 -e=c:\foobar,所有文件都将提取到目录 c:\foobar。如有必要,还将创建该目录。

杂项

您可以使用 Total Commander 打开使用本文代码和二进制文件构建的自解压安装程序,就像打开 zip 文件一样。只需选择文件并按 Ctrl-Pagedown。然后,您可以从自解压二进制文件中选择单个文件,并将它们复制到其他位置。

未来展望

将通过 setupui.exe 提供的用户界面更改为基于 HTA 的用户界面将很有趣。这样,UI 的设计就可以完全留给用户和他的/她的 HTML 技能。为 sfxmaker 添加一个命令行选项以从构建脚本自动化运行它也会非常棒。

历史

  • 版本 1.0.0.39 - 2008/10/19
    • 首次发布
  • 2008/10/23 编辑
    • 添加了一个提示,表明对于 Visual Studio 2005,需要一个最近的 SDK,因为 Visual Studio 2005 中缺少 msi.lib,并且在没有最近 SDK 的情况下 Visual Studio 2005 中缺少 PREfast 支持。
  • 版本 1.0.0.40 - 2008/11/28
    • 添加了使用 -e-x 命令行参数从自解压安装程序提取所有文件的选项。
  • 版本 1.0.0.41 - 2008/11/28
    • 修复了在 Vista 上以“run as invoker”执行级别启动安装程序失败的 bug。
    • 添加了 Vista 执行级别的遗漏序列化。
  • 版本 1.0.0.42 - 2008/12/12
    • 添加了对 -?-h 命令行参数的处理,这将显示一个包含所有命令行参数说明的消息框。
    • 稍微扩大了 UI。
© . All rights reserved.