通过 WiX 安装程序安装 VSIX 包






4.69/5 (7投票s)
使用 WiX Toolset 安装 VSIX 包的实用指南
引言
WiX Toolset 是一个功能强大的工具集,用于创建 Windows 安装包。不幸的是,它的学习曲线相当陡峭,文档也不是它的强项。因此,我决定一步一步地向您展示如何为您的 VSIX 包创建安装程序。我不会涵盖 WiX 的所有功能,因为它并不打算成为一个详尽的 WiX 指南,但我将详细描述部署 VSIX 包所必需的内容。此外,我还将添加一些在创建 WiX 安装程序时可能普遍有用的有趣细节。最终结果应该是一个 MSI 安装文件,可以正确安装和卸载您的 VSIX 包。让我们开始吧。VSIX 本身确实利用了自己的安装程序。但如果您的安装更复杂或需要安装其他组件,您仍应考虑此方法。
必备组件
为了跟进这个例子,您将需要从 2010 年到最新的 2015 年的任何版本的 Visual Studio。除 Express 版本外的任何 SKU 都可以。您需要安装 Visual Studio SDK 和 WiX Toolset。您找到的示例是使用 Visual Studio 2013 和 WiX 3.9 R2 创建的。您可以从这里下载(SDK 和 WiX)。创建必要的项目
为了开始我们的实际示例,让我们首先创建我们稍后将在安装程序中使用到的必要项目。在 Visual Studio 中创建一个新项目,并选择“VSIX Project”。我将其命名为 MyAwesomeExtension。

项目创建后,您将看到 vsixmanifest 设计器。您可以保留所有默认设置。只需确保 Product ID 设置为唯一,并且为了方便起见,不要包含空格。

关于我们的扩展,这应该就够了。我不会专注于创建 Visual Studio 扩展,这足以注册和运行一个扩展。如果您按 F5,您应该会启动另一个 Visual Studio 实例,默认情况下处于实验模式,如果您在“工具”>“扩展和更新”菜单中查看,您应该会找到您新创建的扩展。
接下来是在您的解决方案中添加一个 WiX Setup Project。我将简单地将其命名为 Installer。

就这些。在下一段中,我将向您展示如何使用 WiX 安装您的 VSIX 包。
WiX Toolset 安装程序
首先,第一件事。我们将利用 WixVSExtension 提供的标准自定义操作。为此,我们需要引用 WixVSExtension.dll。您可以在 WiX 安装文件夹中找到它,在我的情况下是C:\Program Files (x86)\WiX Toolset v3.9\bin
。请注意,WiX 安装项目的“添加引用”面板是自定义的,并且与默认面板略有不同。除了提供安装(和卸载)VSIX 包的必要功能外,它还包含许多其他有用的属性和自定义操作,可以简化与 Visual Studio 的交互。您可以在此处找到属性和自定义操作列表。在向项目添加引用后,我们需要在我们的主 wxs 文件(默认是 Product.wxs)中包含 WixVSExtension 命名空间。在默认命名空间旁边的 Wix 元素中,添加 xmlns:VSExtension="http://schemas.microsoft.com/wix/VSExtension"
。最终结果应如下所示
...
现在我们将向我们的 WiX 项目添加另一个引用,它将指向我们的 VSIX 项目。这是为了方便,以便我们可以将 WiX 指向我们的 VSIX 项目的输出。完成此操作后,我们需要定义一个组件,该组件将利用 WixVSExtension 中定义的自定义操作来实际安装我们的 VSIX。在定义 ComponentGroup 的示例所在的片段中,我们将删除其中的所有代码,包括 ComponentGroup 本身。定义如下:
让我们分析一下我们添加的内容。我们添加的第一个元素是一个 Component,我们为了方便将其命名为 C_MyAwesomeExtension
,我们为其组件分配了一个唯一的标识符(以便 MSI 可以跟踪此元素),并指定了此组件应部署到的文件夹。我不会详细介绍组件是什么以及它是如何工作的,我假设您已经知道了,如果不知道,您可以在此处找到更多信息。
在我们的组件中,我们指定了两个元素。最容易理解的肯定是 File 元素。我们为部署 VSIX 所需的文件提供了一个 id,并使用编译的程序集名称为其命名。为了检索名称,我使用了 Wix 由于引用我们添加的项目而生成的变量,并在结果后附加了 .vsix 字符串。现在,每次您引用一个项目时,Wix 都会动态创建几个变量供您使用。您可以在此链接找到它们的完整列表。如果我们引用的是一个输出可执行文件或库的项目,我们可以使用 TargetFileName 变量并省略 .vsix。然而,由于 Wix 默认不知道 VSIX 项目类型和输出,我们需要使用 TargetName 属性并将其与 .vsix 连接起来,才能获得具有正确扩展名的文件名。
我们在 source 属性上也做了同样的事情。通过它,我们指定了复制该文件是为了将其放入 MSI 安装文件。对于 Name 属性,我们将使用一些自动生成的变量来获取我们编译的 VSIX 的正确路径。
VSExtension:VsixPackage 元素
让我们关注本文的主要内容,即 VSExtension:VsixPackage 元素。我将描述我使用的所有属性以及我没有使用的属性,并描述它们产生的行为。
文件
File,顾名思义,需要设置为我们在 MSI 表中使用过的文件名,并指向我们的 VSIX 安装程序。简单地说,它需要与我们之前讨论过的 File 元素的 Id 属性相同。这样,自定义操作就会知道我们要安装的 VSIX 文件在哪里。
PackageId
这是一个非常重要的值。我之前在创建 VSIX 扩展时提到了 Product ID。那就是您的扩展中 vsixmanifest 文件中设置的唯一产品 ID。确保它不包含任何空格,如果包含,请添加引号并正确转义它们。
目标
您可以指定以下值之一:integratedShell、professional、premium、ultimate、vbExpress、vcExpress、vcsExpress、vwdExpress。它将指示注册此扩展所需的 Visual Studio 的哪个版本 (SKU)。
TargetVersion
指定要注册扩展的 Visual Studio 的版本。应包含版本号,例如 Visual Studio 2012 的 11.0,Visual Studio 2015 的 14.0。
Vital
它指示 VSIX 扩展的安装失败是否会导致整个安装回滚。
永久
经常被低估和遗忘的参数。这就是导致有关扩展在 msi 卸载时未卸载的许多抱怨的原因。关于它就这么多。如果设置为 no,当您尝试卸载产品时,您的扩展将被卸载。如果设置为 yes,在用户卸载产品时,您的扩展将不会被删除。
VsixInstallerPathProperty
由于此自定义操作依赖 VsixInstaller.exe 来触发 VSIX 的安装,因此它需要知道 VsixInstaller.exe 的位置才能使用它。建议不要设置此属性,让自定义操作本身来填充它。默认情况下,将使用计算机上最新的 VsixInstaller.exe 来安装 VSIX 包。
信不信由你,这足以让 Wix 安装您的 VSIX 扩展。在我们的例子中,我们目标是 Visual Studio 2013,并接受专业版及以上的所有版本。
幕后
那么这个自定义操作的魔力是什么呢?验证发生了什么最简单的方法是编译我们的项目并启动安装。在我们能够做到这一点之前,我们需要处理两件小事。在我们的 Feature 元素中,我们需要将 ComponentGroupRef 更改为 ComponentRef,并将 id 指向我们的 C_MyAwesomeExtension 组件。另外,为了使输出成为单个文件,我们将告诉 Wix 将 cabinet 集成到 msi 本身。为此,在 MediaTemplate 元素下,我们将添加 EmbedCab 属性并将其值设置为 yes。
我们现在可以编译我们的项目,并定位到构建输出目录。应该有一个名为 Installer.msi 的文件在那里。为了了解发生了什么,我们不能仅仅双击我们新创建的 msi。我们需要从命令提示符启动安装并请求启用详细日志记录。要请求发出日志文件,我们需要运行以下命令:msiexec /i Installer.msi /l*v install.log
。这将告诉 msi 安装程序安装我们的应用程序,并在名为 install.log 的文件中输出详细日志。
如果您执行此命令,您将短暂地看到安装开始,仅此而已。这是因为我们没有为此次安装选择任何 UI。展示如何创建/选择安装程序 UI 不在我们的讨论范围内。
让我们检查一下我们默认的安装文件夹 C:\Program Files (x86)\Installer。Bingo!我们的扩展在那里。现在打开您的 Visual Studio 2013 实例,并检查“扩展和更新”窗口。再次,MyAwesomeExtension 在那里!

打开新创建的日志文件,查看为了实现这一目标所做的工作。打开 install.log 文件并搜索“/skuName:Pro /skuVersion:12.0”。您到达的那一行是我们 VSExtension:VsixPackage 自定义操作执行的命令。完整命令如下:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\VSIXInstaller.exe /q /skuName:Pro /skuVersion:12.0 "C:\Program Files (x86)\Installer\MyAwesomeExtension.vsix" /admin
这里发生了什么?没什么特别的。当您双击 vsix 文件时,vsix 扩展将与 VSIXInstaller.exe 关联,并显示以下窗口:

我们的自定义操作也是如此,它直接调用 VSIXInstaller.exe,以静默模式(因此不显示 UI)触发,并传递必要的参数,以便 VSIXInstaller.exe 执行安装。您认识其他参数吗?没错,它们与我们在 VSExtension:VsixPackage 元素上指定的属性匹配。除了最后的 /admin 参数。它意味着扩展将安装到管理员扩展位置。如果您希望它按用户安装,您需要创建一个 perUser 安装,因此,将 Package InstallScope 设置为 perUser。
您可以查看日志文件,可能会找到大量有趣的信息,例如搜索 VSIXInstaller.exe 以及为适应它而设置的值等。
对于卸载,也做了同样的事情。我们可以使用以下命令启动卸载:msiexec /x Installer.msi /l*v unistall.log
。正如您所见,它与安装类似,只是我们使用了 /x 参数而不是 /i。执行后,您将看到确认提示:

通过确认,将执行卸载。
进入日志文件,再次搜索 /skuName:Pro /skuVersion:12.0。您将登陆触发以下命令的行:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\VSIXInstaller.exe /q /skuName:Pro /skuVersion:12.0 /u:"MyAwesomeExtension.majcica.com.420d4ff9-340c-4867-9247-c85ab370ec7b" /admin
请注意,传递了 /u 参数,它将指示 VSIXInstaller.exe 移除与我们扩展的唯一 ID 匹配的产品 ID(而不是 VSIX 文件)的扩展。
调整安装程序
有几件事情我们可以处理。其中之一是检查是否安装了所需的 Visual Studio。这是为了防止潜在的异常和随后的安装失败。由于这相当简单,我将把必要的信息添加到此帖子中。
我们了解 Visual Studio 安装的所有必要信息。WixVSExtension 以属性的形式将此信息提供给我们。如果安装了 Visual Studio,该属性将被填充,否则不会。我们唯一需要做的就是引用该属性,在我们的情况下,它被称为 VS2013DEVENV,并创建一个验证它是否已设置的条件。
<![CDATA[Installed OR VS2013DEVENV]]>
在产品元素中添加此代码后,编译并启动您的安装,您将收到以下消息,该消息最终会中断并阻止安装。

我能想到的另一件事是为多个版本的 Visual Studio 安装扩展。您可以声明多个组件,每个组件针对同一个文件但 TargetVersion 不同,并为每个组件添加一个条件。示例:
VS2012DEVENV
VS2013DEVENV
结论
我希望我回答了您关于通过 Wix 安装 VSIX 包的所有问题。如果您有任何遗漏,并且想了解更多信息,请随时在评论中提问。
为了完整起见,我现在将列出 Product.wxs 文件的完整内容。
<![CDATA[Installed OR VS2013DEVENV]]>
祝您编码愉快!关注点
如果您知道任何应该添加的信息、我遗漏的细节或您无法实现的功能(与 VSIX 和 WiX 相关),请在评论中提及。
如果对此主题有其他发现,我将更新本文。
历史
初始版本。