加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-13 22:42:35 所属栏目:Windows 来源:网络整理
导读:我正在尝试使用 WIX创建一个安装项目,这将允许我安装单个产品的多个功能.如何更新其中一个已安装的功能(独立于其他已安装的功能),而无需重新安装功能树中的其他功能? 例如,我希望能够拥有一个名为HelloWolrd的项目(返回HelloWolrd),其中(惊喜)打印出“Hello
我正在尝试使用 WIX创建一个安装项目,这将允许我安装单个产品的多个功能.如何更新其中一个已安装的功能(独立于其他已安装的功能),而无需重新安装功能树中的其他功能?

例如,我希望能够拥有一个名为HelloWolrd的项目(返回HelloWolrd),其中(惊喜)打印出“Hello world!”屏幕上.假设我有三个这样的hello world应用程序,Hello World 1,Hello World 2和Hello World 3.每个应用程序都会在屏幕上显示Hello World 1,2或3.我想要的是创建一个MSI,它默认安装所有这三个“功能”,但也允许在以后单独升级每个功能.

这是我的解决方案布局:

Solution Explorer 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="SoftwareHelloWorldInstallerHelloWorld1Install" 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="SoftwareHelloWorldInstallerHelloWorld2Install" 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="SoftwareHelloWorldInstallerHelloWorld3Install" 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 Error http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg

我更新了我的代码以允许卸载这些功能并允许使用升级代码,但是已经卸载了所有功能,并重新安装了所有这些功能.

– 真实世界的应用 –

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

任何帮助都会受到批评,

谢谢!

编辑:

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

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

我们有一个中等大小的软件,要求我们拥有多个支持应用程序,这些应用程序可以在许多不同的服务器上运行.我们目前的升级进程使得以可靠的方式升级代码变得非常困难.目前我们使用自解压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安装所有这三个,但是然后独立更新每个MSI,而不会影响任何其他已安装的组件.

因此,为了证明这一点,我创建了上面的三个控制台应用程序,它们将显示“Hello World 1!”,“Hello World 2!”和“Hello World 3!”.然后在我们发布初始MSI之后,让我们说找到一个“bug”,要求我们让HelloWorld1说“Hello World 1!Updated”.代替.以下是我们将要模拟的内容:

>通过在命令提示符下执行此命令来创建Product.wixobj:candle.exe Product.wxs请记住,为了调用candle.exe或任何WIX命令,Wix安装目录应该在PATH变量中. (Short tutorial on updating PATH environment variable)另外,请在Product.wxs文件所在的目录中执行命令.
>创建产品的第一个版本(比方说1.0):light.exe Product.wixobj -out ProductA-1.0.msi
>现在找到一个错误(将HelloWorld1的输出更改为“Hello World 1!Updated.”)然后更新程序集版本和文件版本.这很重要,因为这是WIX可以告诉exe的不同之处.
>运行与第一步相同的命令(为了更好地衡量):candle.exe Product.wxs
>运行与第二步几乎相同的命令:light.exe Product.wixobj -out ProductA-1.1.msi请注意,这是版本1.1而不是1.0(这是带有我们更新代码的msi).但是,我们不想只是安装它,继续阅读.
>这是有趣的部分,我们使用以下命令获得两个MSI的区别:torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
>现在我们从这里创建补丁文件(Patch.wxs将在下面解释):candle.exe Patch.wxs
>我们现在将使用以下命令创建WixMsp文件:light.exe Patch.wixobj -out Patch.WixMsp
>现在,有趣的部分.使用以下命令创建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!Updated”.

现在,对于神奇的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>

看起来不是很多,是吗?嗯,最有趣的部分是这些:

>< PatchBaseline Id =“RTM”/> – 如果你回想起这个用于我们的补丁msi的创建.上面的最后一步中引用了“RTM”:-t RTM – 这些必须匹配.
>< ComponentRef Id =“HelloWorld1Component”/> – 这将补丁指向要更新的正确组件,在我们的示例中为HelloWorld1Component.

如果你一直在搜索,上面的代码可能看起来很熟悉,因为它来自Peter Marcu’s Blog:WiX: Building a Patch using the new Patch Building System – Part 3

我也非常依赖于Alex Shevchuk’s Blog:From MSI to WiX,Part 8 – Major Upgrade

如果你想知道,“哇,那是很多步骤,为什么有人会做这么多步骤?”,请记住,一旦完成了艰苦的工作(上面),你需要将它移到你的集成例程中.这是正确的,集成,集成!你怎么做到这一点?嗯,这是一个更多的研究,也许是一篇博客文章? – 可能.为了让你从右脚出发,这是一篇很棒的文章,发表于Automate Releases With MSBuild And Windows Installer XML.

哇,我希望你能读完所有这些(你们两个人),并且学到了很多东西.我希望这可以帮助除我以外的其他人.

谢谢!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读