升级 WIX 功能树中的单个功能,无需卸载/升级其他功能

发布于 2024-08-10 23:58:16 字数 5146 浏览 2 评论 0原文

我正在尝试使用 WIX 创建一个安装项目,这将允许我安装单个产品的多个功能。如何更新已安装的功能之一(独立于其他已安装的功能),而无需重新安装功能树中的其他功能?

例如,我希望能够有一个名为 HelloWolrd 的项目(回到 HelloWolrd),它(令人惊讶)打印“Hello world!”在屏幕上。假设我有三个 hello world 应用程序,Hello World 1、Hello World 2 和 Hello World 3。每个应用程序都在屏幕上分别打印 Hello World 1、2 或 3。我想要创建一个 MSI,默认情况下安装所有这三个“功能”,但也允许稍后单独升级每个功能。

这是我的解决方案的布局:

解决方案资源管理器 http://img12.imageshack.us/ img12/5671/solutionexplorerm.jpg

我的 WIX Product.wxs 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="ca484210-c719-4b2e-b960-45212d407c11" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0" Manufacturer="HelloWorldInstaller" UpgradeCode="68eeb8cb-9ef3-443c-870c-9b406129f7ff">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <!-- Create Directory Structure -->
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="Hello World" />
            </Directory>
            <Directory Id="DesktopFolder" Name="Desktop"/>
        </Directory>

        <DirectoryRef Id="INSTALLLOCATION">
            <Component Id="HelloWorld1" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld1\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld1.exe" Name="$(var.HelloWorld1.TargetFileName)" Source="$(var.HelloWorld1.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld1ApplicationDesktopShortcut" Name="Hello World 1" Description="Hello World Application 1" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>

            </Component>
            <Component Id="HelloWorld2" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld2\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld2.exe" Name="$(var.HelloWorld2.TargetFileName)" Source="$(var.HelloWorld2.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld2ApplicationDesktopShortcut" Name="Hello World 2" Description="Hello World Application 2" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
            <Component Id="HelloWorld3" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld3\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld3.exe" Name="$(var.HelloWorld3.TargetFileName)" Source="$(var.HelloWorld3.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld3ApplicationDesktopShortcut" Name="Hello World 3" Description="Hello World Application 3" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
        </DirectoryRef>

        <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
            <ComponentRef Id="HelloWorld1"/>
        </Feature>
        <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
            <ComponentRef Id="HelloWorld2"/>
        </Feature>
        <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
            <ComponentRef Id="HelloWorld3"/>
        </Feature>

    </Product>
</Wix>

现在,当构建此文件时,它会按照您的预期安装功能。但是,当您对 HelloWorld1.vb 进行修改并重新编译时,我希望它能够仅重新安装(升级)该功能,而不是全部功能。

当我更新一个文件并重建解决方案,然后尝试安装 msi 时,出现此错误:

MSI 错误 http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg

我更新了代码以允许卸载功能并允许使用升级代码,但未安装所有功能,并重新安装所有功能。


-- 现实世界的应用程序 --

现实世界的应用程序是一个大型软件包,需要多个支持应用程序作为服务/计划任务定期运行。我希望将这些支持应用程序安装到一个 MSI 中,这样我们就不会经历单独推出每个 exe 的噩梦。我知道,如果我们对其中一个 exe 有更新,我们可以手动编译该 exe 并将其推出,但我想以完全可重现的方式执行此操作。

如有任何帮助,将不胜感激,

谢谢!

编辑:

我添加了从 Google 代码 下载的源。再次感谢!

I'm trying to create a setup project using WIX that will allow me to install multiple features of a single product. How can I update one of the installed features (which is independent of the other installed features) without having to reinstall the other features in the feature-tree?

For example, I want to be able to have a project (going back to HelloWolrd) called HelloWolrd, which (surprise) prints "Hello world!" on the screen. Let's say that I have three of these hello world applications, Hello World 1, Hello World 2, and Hello World 3. Each of which prints on the screen Hello World 1, 2, or 3, respectfully. What I would like is to create an MSI which by default installs all three of these "features" but also allows upgrading of each feature individually at a later time.

Here is my layout of my solution:

Solution Explorer http://img12.imageshack.us/img12/5671/solutionexplorerm.jpg

My WIX Product.wxs file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="ca484210-c719-4b2e-b960-45212d407c11" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0" Manufacturer="HelloWorldInstaller" UpgradeCode="68eeb8cb-9ef3-443c-870c-9b406129f7ff">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <!-- Create Directory Structure -->
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="Hello World" />
            </Directory>
            <Directory Id="DesktopFolder" Name="Desktop"/>
        </Directory>

        <DirectoryRef Id="INSTALLLOCATION">
            <Component Id="HelloWorld1" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld1\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld1.exe" Name="$(var.HelloWorld1.TargetFileName)" Source="$(var.HelloWorld1.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld1ApplicationDesktopShortcut" Name="Hello World 1" Description="Hello World Application 1" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>

            </Component>
            <Component Id="HelloWorld2" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld2\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld2.exe" Name="$(var.HelloWorld2.TargetFileName)" Source="$(var.HelloWorld2.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld2ApplicationDesktopShortcut" Name="Hello World 2" Description="Hello World Application 2" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
            <Component Id="HelloWorld3" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
                <RegistryKey Root="HKCU" Key="Software\HelloWorldInstaller\HelloWorld3\Install" Action="createAndRemoveOnUninstall">
                    <RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
                </RegistryKey>

                <File Id="HelloWorld3.exe" Name="$(var.HelloWorld3.TargetFileName)" Source="$(var.HelloWorld3.TargetPath)" DiskId="1" Checksum="yes">
                    <Shortcut Id="HelloWorld3ApplicationDesktopShortcut" Name="Hello World 3" Description="Hello World Application 3" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
                </File>
            </Component>
        </DirectoryRef>

        <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
            <ComponentRef Id="HelloWorld1"/>
        </Feature>
        <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
            <ComponentRef Id="HelloWorld2"/>
        </Feature>
        <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
            <ComponentRef Id="HelloWorld3"/>
        </Feature>

    </Product>
</Wix>

Now, when this is built, it installs the features as you would expect. However, when you make a modification to HelloWorld1.vb and recompile, I would like it to be able to reinstall (upgrade) only that feature, not all of them.

When I update one file, and rebuild the solution, then try to install the msi, i get this error:

MSI Error http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg

I updated my code to allow for uninstalling of the features and allow the use of upgrade codes, but that un-installed all of the features, and re-installed all of them.


-- Real world application --

The real world application to this is a large software package that needs multiple support applications that run as services/scheduled tasks on a regular basis. I would like to get the install of these supporting apps into one MSI allowing us to not have such a nightmare of rolling out each exe individually. I know that if we have an update to one of the exe's that we could just manually compile that exe and roll it out, but I'd like to do this in a completely reproducible manner.

Any help would be appriciated,

Thank you!

EDIT:

I added the source for download from Google Code. Thanks again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

跨年 2024-08-17 23:58:16

我弄清楚了这一点,并认为我会将答案发布在这里,以供其他人将来参考。所以我已经充分解释了这个问题,我将更深入地探讨现实世界的场景。

我们有一个相当大的软件,需要我们有多个支持应用程序在许多不同的服务器上运行。我们当前的升级进程使得以可靠的方式升级代码变得相当困难。目前,我们使用自解压 exe 将代码部署到不同的服务器。当我们有如此大量的支持应用程序时,就会出现问题,以至于很难确保使用正确的配置设置等正确安装应用程序。为了解决这个问题,我们正在研究能够而不是压缩每个应用程序的能力。对于支持应用程序,我们创建一个安装程序 (MSI),它允许基础架构团队向每台给定计算机安装一组特定的支持应用程序。当我们进行重大更改(例如从 1.0 到 2.0)时,我们将进行完整升级安装(这意味着所有服务/进程都需要停止、卸载、安装和启动。)当我们进行较小更改时,我们只想停止并重新安装受影响的服务/进程,而无需触及其他应用程序。现在,我已经闲聊够了,让我们开始解决方案

我修改了 WIX Product.wxs 以删除快捷方式,因为我们在我们的场景中并不真正需要它们。这是更新后的 wxs 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Product Id="13C373D3-5C27-487e-A020-C2C89E4607B1" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0"
      Manufacturer="HelloWorldInstaller" UpgradeCode="E7CB3C76-4D51-48a8-BFB4-6D11B2E2E65B">

  <Package InstallerVersion="200" Compressed="yes" />

  <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
  <FeatureRef Id="HelloWorld1Feature" />
  <FeatureRef Id="HelloWorld2Feature" />
  <FeatureRef Id="HelloWorld3Feature" />
 </Product>

 <Fragment>
  <Directory Id="TARGETDIR" Name="SourceDir">
   <Directory Id="ProgramFilesFolder">
    <Directory Id="INSTALLLOCATION" Name="Hello World" />
   </Directory>
   <Directory Id="DesktopFolder" Name="Desktop"/>
  </Directory>
 </Fragment>

 <Fragment>
  <DirectoryRef Id="INSTALLLOCATION">
   <Directory Id="HelloWorld1Directory" Name="Hello World 1">
    <Component Id="HelloWorld1Component" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
     <File Id="HelloWorld1.exe" Name="HelloWorld1.exe" Source="HelloWorld1.exe" DiskId="1" Checksum="yes" />    
    </Component>
   </Directory>
   <Directory Id="HelloWorld2Directory" Name="Hello World 2">
    <Component Id="HelloWorld2Component" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
     <File Id="HelloWorld2.exe" Name="HelloWorld2.exe" Source="HelloWorld2.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
   <Directory Id="HelloWorld3Directory" Name="Hello World 3">
    <Component Id="HelloWorld3Component" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
     <File Id="HelloWorld3.exe" Name="HelloWorld3.exe" Source="HelloWorld3.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
  </DirectoryRef>
 </Fragment>

 <Fragment>
  <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
   <ComponentRef Id="HelloWorld1Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
   <ComponentRef Id="HelloWorld2Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
   <ComponentRef Id="HelloWorld3Component"/>
  </Feature>
 </Fragment>
</Wix>

现在,对于我们的小升级,我们将考虑为我们的组件发布补丁。

例如,假设我们有一个 ProductA,它具有三个组件 - 1,2 和 3。这三个组件必须作为服务或计划任务运行。由于我们产品的性质,我们无法关闭所有服务来更新或修复我们的某个组件。因此,如果在安装版本 1.0 后,我们发现组件 2 中存在错误,但我们不希望 1 或 3 受到应用于此错误的修复的影响,我们将为组件 2 发布补丁,因此只有组件 2 会受到影响。

对于上面的简单示例,我们使用 HelloWorld1、HelloWorld2 和 HelloWorld3 作为软件应用程序中的 3 个组件。我们的想法是,我们应该能够使用一个 MSI 安装所有三个组件,然后独立更新每个组件,而不会影响任何其他已安装的组件。

因此,为了演示这一点,我创建了上面的三个控制台应用程序,它们将显示“Hello World 1!”、“Hello World 2!”和“Hello World 3!”。然后,在我们发布初始 MSI 后,假设我们发现了一个“错误”,要求我们让 HelloWorld1 说“Hello World 1!已更新”。反而。我们将执行以下操作来模拟这一点:

  1. 通过在命令提示符处执行以下命令来创建 Product.wixobj:
    candle.exe Product.wxs
    请记住,为了调用Candle.exe 或任何 WIX 命令,Wix 安装目录应位于您的 PATH 变量中。 (更新 PATH 环境变量的简短教程) 另外,请在同一目录中执行命令作为您的 Product.wxs 文件。
  2. 创建产品的第一个版本(假设为 1.0):
    light.exe Product.wixobj -out ProductA-1.0.msi
  3. 现在找到一个错误(将 HelloWorld1 的输出更改为“Hello世界 1!已更新。”)然后更新程序集版本和文件版本。这很重要,因为 WIX 可以通过这种方式来区分 exe 的不同。
  4. 运行与第一步相同的命令(为了更好地衡量):
    candle.exe Product.wxs
  5. 运行与第二步几乎相同的命令:
    light.exe Product.wixobj -out ProductA-1.1.msi
    请注意,这是版本 1.1,而不是 1.0(这是带有我们更新代码的 msi)。但是,我们不想只安装这个,继续阅读。
  6. 这是有趣的部分,我们使用以下命令获得两个 MSI 的差异:
    torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
  7. 现在我们由此创建补丁文件(Patch.wxs 将在下面解释):
    candle.exe Patch.wxs
  8. 我们现在将使用以下命令创建 WixMsp 文件:
    light.exe Patch.wixobj -out Patch.WixMsp
  9. 现在,有趣的部分。使用以下命令创建 MSP 文件:
    pyro.exe Patch.WixMsp -out Patch.msp -t RTM Diff.Wixmst

现在,如果一切按计划进行,您应该有两个 msi 和一个 msp 文件。如果您安装第一个 msi (ProductA-1.0.msi) 并运行 HelloWorld1.exe,您应该会看到消息“Hello World 1!”。只是为了好玩(和示例),运行其他应用程序并让它们保持运行(我内置了一个停止以保持它们打开)。关闭 HelloWorld1.exe,因为我们现在要应用该 exe 的更新,但这样做不会影响 HelloWorld2.exe 或 HelloWorld3.exe。如果您现在安装 msp (Patch.msp) 文件,然后运行 ​​HelloWorld1.exe,您将看到更新的消息“Hello World 1!已更新”。

现在,对于神奇 Patch.wxs 文件:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Patch
   AllowRemoval="yes"
   Manufacturer="Dynamo Corp"
   MoreInfoURL="http://www.dynamocorp.com/"
   DisplayName="Sample Patch"
   Description="Small Update Patch"
   Classification="Update"
        >

  <Media Id="5000" Cabinet="RTM.cab">
   <PatchBaseline Id="RTM"/>
  </Media>

  <PatchFamilyRef Id="SamplePatchFamily"/>
 </Patch>

 <Fragment>
  <PatchFamily Id='SamplePatchFamily' Version='1.0.0' Supersede='yes'>
   <ComponentRef Id="HelloWorld1Component"/>
  </PatchFamily>
 </Fragment>
</Wix>

看起来并不多,不是吗?好吧,最有趣的部分是这些:

  1. - 如果您还记得的话,这在我们创建补丁 msi 时使用过。在上面的最后一步中引用了“RTM”:-t RTM - 这些必须匹配。
  2. - 这将补丁指向要更新的正确组件,在我们的例子中是 HelloWorld1Component。

如果您一直在进行任何搜索,上面的代码可能看起来很熟悉,因为它来自 Peter Marcu 的博客: WiX:使用新版本构建补丁补丁构建系统 - 第 3 部分

我还严重依赖 Alex Shevchuk 的博客来自MSI 到 WiX,第 8 部分 - 主要升级

如果您想知道,“哇,这有很多步骤,为什么有人要做这么多步骤?”,请记住,一旦完成艰苦的工作(上面) ,您需要将其移至您的集成例程中。没错,整合,整合,整合!你如何做到这一点?好吧,这还需要更多的研究,也许还需要一篇博客文章? - 大概。为了让您顺利起步,这里有一篇关于使用 MSBuild 自动发布的精彩文章以及 Windows Installer XML

哇,我希望您(你们两个)阅读了所有这些内容,并学到了很多东西。我希望这对我以外的人有帮助。

谢谢你!

I got this figured out and thought I would post the answer here for future reference for others. So I have fully explained the problem, I will go in to more depth of the real world scenario.

We have a moderately large piece of software that requires us to have multiple supporting applications that run on a number of different servers. Our current progression of upgrades makes it moderately difficult to upgrade code in a reliable fashion. Currently we use self extracting exe's to rollout our code to the different servers. The problem arises when we have such a large number of supporting applications that it becomes hard to make sure that the applications got installed correctly with the correct configuration settings, etc. To solve this problem we are looking into the ability to instead of compressing each of the supporting applications, we create a single installer (MSI) that will allow the infrastructure team to install a specific set of supporting applications to each given machine. When we have a major change (for example from 1.0 to 2.0) we will do a full upgrade install (meaning all services/processes will need to be stopped, un-installed, installed, and started.) When we have a minor change, we would like to only have to stop and reinstall the affected services/processes, without touching other applications. Now, enough of me rambling, lets get to the solution:

I modified the WIX Product.wxs to remove the shortcuts as we don't really need them in our scenario. Here is the updated wxs file:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Product Id="13C373D3-5C27-487e-A020-C2C89E4607B1" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0"
      Manufacturer="HelloWorldInstaller" UpgradeCode="E7CB3C76-4D51-48a8-BFB4-6D11B2E2E65B">

  <Package InstallerVersion="200" Compressed="yes" />

  <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
  <FeatureRef Id="HelloWorld1Feature" />
  <FeatureRef Id="HelloWorld2Feature" />
  <FeatureRef Id="HelloWorld3Feature" />
 </Product>

 <Fragment>
  <Directory Id="TARGETDIR" Name="SourceDir">
   <Directory Id="ProgramFilesFolder">
    <Directory Id="INSTALLLOCATION" Name="Hello World" />
   </Directory>
   <Directory Id="DesktopFolder" Name="Desktop"/>
  </Directory>
 </Fragment>

 <Fragment>
  <DirectoryRef Id="INSTALLLOCATION">
   <Directory Id="HelloWorld1Directory" Name="Hello World 1">
    <Component Id="HelloWorld1Component" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
     <File Id="HelloWorld1.exe" Name="HelloWorld1.exe" Source="HelloWorld1.exe" DiskId="1" Checksum="yes" />    
    </Component>
   </Directory>
   <Directory Id="HelloWorld2Directory" Name="Hello World 2">
    <Component Id="HelloWorld2Component" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
     <File Id="HelloWorld2.exe" Name="HelloWorld2.exe" Source="HelloWorld2.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
   <Directory Id="HelloWorld3Directory" Name="Hello World 3">
    <Component Id="HelloWorld3Component" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
     <File Id="HelloWorld3.exe" Name="HelloWorld3.exe" Source="HelloWorld3.exe" DiskId="1" Checksum="yes" />
    </Component>
   </Directory>
  </DirectoryRef>
 </Fragment>

 <Fragment>
  <Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
   <ComponentRef Id="HelloWorld1Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
   <ComponentRef Id="HelloWorld2Component"/>
  </Feature>
 </Fragment>
 <Fragment>
  <Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
   <ComponentRef Id="HelloWorld3Component"/>
  </Feature>
 </Fragment>
</Wix>

Now along with this, for our minor upgrades, we will be looking at releasing patches for our components.

For example, let's say we have a ProductA, which has three components - 1,2, and 3. These three components must run either as services, or scheduled tasks. The nature of our product, we cannot shut down all of our services to update or fix one of our components. So, if after we've installed version 1.0, we find a bug in component 2, but we don't want 1 or 3 to be affected by the fix being applied to this bug, we will be releasing a patch for component 2, thus only component 2 will be affected.

For our quick example above, we are using HelloWorld1, HelloWorld2, and HelloWorld3 as our 3 components in our software application. The thought is that we should be able to install all three with one MSI, but then update each one independently without it affecting any of the other installed components.

So, to demonstrate this, I have created the three console applications above that will display "Hello World 1!", "Hello World 2!", and "Hello World 3!". Then after we release the initial MSI, lets say we find a "bug" that requires us to have HelloWorld1 say "Hello World 1! Updated." instead. Here is what we will do to simulate this:

  1. Create the Product.wixobj by executing this command at the command prompt:
    candle.exe Product.wxs
    Please remember that in order to call the candle.exe or any of the WIX commands, the Wix install directory should be in your PATH variable. (Short tutorial on updating PATH environment variable) Also, please perform the commands in the same directory as your Product.wxs file.
  2. Create the first version of your product (lets say 1.0):
    light.exe Product.wixobj -out ProductA-1.0.msi
  3. Now find a bug (change the output of HelloWorld1 to say "Hello World 1! Updated.") then update the assembly version and file version. This is important as this is how WIX can tell the exe's are different.
  4. Run the same command as step one (for good measure):
    candle.exe Product.wxs
  5. Run nearly the same command as step two:
    light.exe Product.wixobj -out ProductA-1.1.msi
    Notice that this is version 1.1 instead of 1.0 (this is the msi with our updated code). However, we don't want to just install this, keep reading.
  6. Here is the fun part, we get the difference in the two MSIs with the following command:
    torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
  7. Now we create the patch file from this (Patch.wxs will be explained below):
    candle.exe Patch.wxs
  8. We will now create the WixMsp file with this command:
    light.exe Patch.wixobj -out Patch.WixMsp
  9. And now, the fun part. Create the MSP file with this command:
    pyro.exe Patch.WixMsp -out Patch.msp -t RTM Diff.Wixmst

Now, if everything went according to plan, you should have two msi's and one msp file. If you install the first msi (ProductA-1.0.msi) and run HelloWorld1.exe, you should see the message, "Hello World 1!". Just for fun (and example), run both the other applications and leave them running (I built in a stop to keep them open). Close HelloWorld1.exe as we are now going to apply the update for that exe, but in doing so we will not affect HelloWorld2.exe or HelloWorld3.exe. If you now install the msp (Patch.msp) file, and then run HelloWorld1.exe, you will see the updated message, "Hello World 1! Updated."

Now, for the magical Patch.wxs file:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <Patch
   AllowRemoval="yes"
   Manufacturer="Dynamo Corp"
   MoreInfoURL="http://www.dynamocorp.com/"
   DisplayName="Sample Patch"
   Description="Small Update Patch"
   Classification="Update"
        >

  <Media Id="5000" Cabinet="RTM.cab">
   <PatchBaseline Id="RTM"/>
  </Media>

  <PatchFamilyRef Id="SamplePatchFamily"/>
 </Patch>

 <Fragment>
  <PatchFamily Id='SamplePatchFamily' Version='1.0.0' Supersede='yes'>
   <ComponentRef Id="HelloWorld1Component"/>
  </PatchFamily>
 </Fragment>
</Wix>

Doesn't look like much, does it? Well, the most interesting parts are these:

  1. <PatchBaseline Id="RTM"/> - This if you recall is used in our creation of the patch msi. The "RTM" is referred to in the last step above: -t RTM - These have to match.
  2. <ComponentRef Id="HelloWorld1Component"/> - This points the patch to the correct component to update, in our case HelloWorld1Component.

If you've been doing any searching around, the above code may seem familiar because it came from Peter Marcu's Blog: WiX: Building a Patch using the new Patch Building System - Part 3

I also relied heavily on Alex Shevchuk's Blog: From MSI to WiX, Part 8 - Major Upgrade

If you're wondering, "Wow, that's a lot of steps, why would anyone do this many steps?", please remember that once the hard work (above) is done, you need to move this into your integration routine. Thats right, integrate, integrate, integrate! How do you do this? Well, thats a bit more research, and maybe a blog post? - Probably. To get you off on the right foot, here is an awesome article on Automate Releases With MSBuild And Windows Installer XML.

Wow, I hope you read all of this (all two of you), and learned a lot. I hope this helps someone other than myself.

Thank you!

一杯敬自由 2024-08-17 23:58:16

听起来您已经弄清楚了升级方案,现在您只需要弄清楚 在主要 MSI 升级中将 RemoveExistingProducts 放置在何处,以便功能在未更改时不会重新安装:)

Sounds like you figured out the upgrade scenario, now you just need to figure out Where to place RemoveExistingProducts in a major MSI upgrade so that features aren't reinstalled if they haven't changed :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文