Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
升级WIX功能树中的单个功能,而不卸载/升级其他功能_Wix_Windows Installer_Setup Project_Wix3_Feature Upgrade - Fatal编程技术网

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

升级WIX功能树中的单个功能,而不卸载/升级其他功能,wix,windows-installer,setup-project,wix3,feature-upgrade,Wix,Windows Installer,Setup Project,Wix3,Feature Upgrade,我正在尝试创建一个安装项目,使用它可以安装单个产品的多个功能。如何更新其中一个已安装的功能(独立于其他已安装的功能),而不必在功能树中重新安装其他功能 例如,我希望能够有一个名为HelloWald的项目(回到HelloWald),它(惊喜地)在屏幕上打印“HelloWorld!”。假设我有三个hello world应用程序,hello world 1、hello world 2和hello world 3。每一个都会在屏幕上恭敬地打印Hello World 1、2或3。我想要的是创建一个MSI,

我正在尝试创建一个安装项目,使用它可以安装单个产品的多个功能。如何更新其中一个已安装的功能(独立于其他已安装的功能),而不必在功能树中重新安装其他功能

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

以下是我的解决方案布局:

我的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中,这样我们就不会有单独推出每个exe的噩梦。我知道如果我们有一个exe的更新,我们可以手动编译该exe并将其推出,但我想以完全可复制的方式来做这件事

任何帮助都将受到感谢

非常感谢。 编辑:


我添加了源代码以便从下载。再次感谢

听起来你已经了解了升级方案,现在你只需要了解一下,如果功能没有更改,就不会重新安装:)

我已经了解了,我想我会在这里发布答案,供其他人参考。因此,我已经充分解释了这个问题,我将更深入地了解真实世界的情况

我们有一个中等规模的软件,需要我们有多个支持应用程序,运行在多个不同的服务器上。我们目前的升级进度使得以可靠的方式升级代码变得相当困难。目前,我们使用自解压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>
看起来不太像,是吗?嗯,最有趣的部分是:

  • -如果您还记得的话,这是在我们创建补丁msi时使用的。“RTM”在上面的最后一步中提到:
    -t RTM
    -这些必须匹配
  • -这将补丁指向要更新的正确组件,在我们的示例中是HelloWorld1组件 如果您一直在搜索,上面的代码可能看起来很熟悉,因为它来自:

    我还严重依赖于:

    如果您想知道,“哇,这是很多步骤,为什么有人要做这么多步骤?”请记住,一旦完成了(上面)的艰苦工作,您需要将其转移到您的集成例程中。没错,整合,整合,整合!你是怎么做到的?好吧,这是更多的研究,也许是一篇博文可能为了让你走上正轨,这里有一篇很棒的文章

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


    非常感谢。为什么避免重新安装功能很重要?结果不一样吗?我认为除了查看安装日志之外,没有其他方法可以区分这两者之间的区别。@wcoenen-我之所以想避免重新安装其他功能,是因为我们在FeatureA中发现了一个bug,需要修复它。如果错误不影响功能B
    <?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>