WiX条件功能/组件在卸载时孤立

时间:2011-09-15 15:43:02

标签: wix windows-installer global-assembly-cache

编辑:引用自己,因为我在下面的评论之一中更好地总结了这个问题......

  

安装软件包时,我的条件是真的,但是   删除时不正确。我希望MSI能够记住它有   安装条件组件并使用卸载将其删除,   但这种情况并非如此。我试图找出A)正确的方法   清理这个孤立的组件,B)保护的最佳方法   在将来反对这个问题。

我想我的问题归结为,在卸载产品后删除孤立的功能/组件是否安全?有没有办法检查什么,如果有的话,仍然引用我认为是一个孤儿的组件?我如何修复我的安装程序以防止将来发生这种情况?

我们有一个wix项目来安装库Foo。此安装程序将Foo.dll的副本放入GAC,默认情况下放置文件夹Program Files\Reference Assemblies\Foo\<version>。安装程序还添加了两个注册表项,一个是自定义键,用于存储Foo文件夹的路径,以便在将来的安装中重用,另一个用于告诉Visual Studio在搜索已安装的库时包含完整的<version>文件夹路径,以便Foo出现在“添加引用”对话框中。可以一次在机器上安装多个版本的Foo库,每个版本都位于Foo下的相应<version>文件夹中。

Foo 2.0.0有一个错误通过测试,Foo 2.0.1包含错误修复,没有其他更改。由于错误修复是唯一的变化,我们决定向GAC添加一个策略文件,将Foo 2.0.0的引用重定向到Foo 2.0.1。此策略文件已作为新功能内的新组件添加到安装程序中。添加了升级标记以在安装Foo 2.0.1时检测并删除Foo 2.0.0。策略功能的安装是在检测到Foo 2.0.0的条件下进行的。一切似乎都在起作用,Foo 2.0.1被推出了。

现在,一年后,我们发现我们再次错过了注意到错误,这次是在安装程序设置而不是库代码中。事实证明,当Foo 2.0.1替换2.0.0,然后卸载时,策略文件将被孤立并保留在GAC中,同时删除所有其他文件和密钥。我已经在一个干净的Windows安装上测试了这个(虚拟机可能非常有用),并确认可以复制问题,即没有对该组件的额外引用导致它留下来。

所有这些最初都是在WiX 3.0中完成的,但我们最近采用了WiX 3.5。我们的WiX代码如下所示:

<Product Id="Guid 1" Name="Foo v2.0.1" Language="1033" Version="2.0.1" Manufacturer="My Team" UpgradeCode="Guid 2">

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

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

  <Upgrade Id="Guid 2">
    <UpgradeVersion Minimum="2.0.0" Maximum="2.0.0" IncludeMaximum="yes" IncludeMinimum="yes" OnlyDetect="no" Property="UPGRADE2X0X0"></UpgradeVersion>
  </Upgrade>

  <Property Id="FOODIR">
    <RegistrySearch Id="FooPath" Type="directory" Root="HKLM" Key="Software\Foo" Name="InstallPath"></RegistrySearch>
  </Property>

  <Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFilesFolder">
      <Directory Id="RefAssemb" Name="Reference Assemblies">
        <Directory Id="FOODIR" Name="Foo">
          <Component Id="FooLibPath" Guid="Guid 3">
            <RegistryKey Root="HKLM" Key="Software\Foo" Action="createAndRemoveOnUninstall">
              <RegistryValue Name="InstallPath" Type="string" Value="[FOODIR]" KeyPath="yes"></RegistryValue>
            </RegistryKey>
          </Component>
          <Directory Id="FOOVERSION" Name="v2.0.1">
            <Component Id="Foo_VSFile" Guid="Guid 4">
              <File Id="Foo_DLL" Source="$(sys.CURRENTDIR)2.0.1\Foo.dll" KeyPath="yes"></File>
            </Component>
            <Component Id="Foo_VSRegKey" Guid="Guid 5">
              <RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\.NETFramework\v3.5\AssemblyFoldersEx\Foo v2.0.1" Action="createAndRemoveOnUninstall">
                <RegistryValue Type="string" Value="[FOOVERSION]" KeyPath="yes"></RegistryValue>
              </RegistryKey>
            </Component>
            <Directory Id="FOOGAC" Name="GAC">
              <Component Id="Foo_GAC" Guid="Guid 6">
                <File Id="Foo" Source="$(sys.CURRENTDIR)2.0.1\Foo.dll" KeyPath="yes" Assembly=".net"></File>
              </Component>
              <Component Id="Foo_Policy_2x0x1" Guid="Guid 7">
                <File Id="Foo_PolicyDLL" Source="$(sys.CURRENTDIR)2.0.1\policy.2.0.Foo.dll" KeyPath="yes" Assembly=".net"></File>
                <File Id="Foo_PolicyConfig" Source="$(sys.CURRENTDIR)2.0.1\policy.2.0.Foo.config" CompanionFile="Foo_PolicyDLL"></File>
              </Component>
            </Directory>
          </Directory>
        </Directory>
      </Directory>
    </Directory>
  </Directory>

  <Feature Id="ProductFoo" Level="1">

      <ComponentRef Id="Foo_GAC"/>

      <Feature Id="Foo_VSSupport" Level="1">
        <ComponentRef Id="FooLibPath"/>
        <ComponentRef Id="Foo_VSFile"/>
        <ComponentRef Id="Foo_VSRegKey"/>
      </Feature>

      <Feature Id="Foo_Policy_v2x0x1" Level="0">
        <ComponentRef Id="Foo_Policy_2x0x1"/>
        <Condition Level="1">UPGRADE2X0X0</Condition>
      </Feature>

  </Feature>

</Product>

1 个答案:

答案 0 :(得分:1)

  

在a之后删除孤立的功能/组件是否安全   产品是否已卸载?

不,不是。如果您只是删除它,它的组件注册信息仍保留在机器上。

  

有没有办法检查什么,如果有的话,仍在引用   我认为是孤儿的一个组成部分?

不是真的。但是,如果有某些内容引用了您的某个组件,则很可能是您开发的另一种产品或当前产品的旧版本未正确卸载。

随机产品不太可能引用您的组件或组件。

  

如何修复我的安装程序以防止这种情况发生   未来?

使用卸载旧组件的主要升级并安装新组件。没有特殊的政策文件,没有条件安装或删除。

  

可以在机器上安装多个版本的Foo库   一次,每个都将位于相应的文件夹中   在Foo。

为什么呢?如果您有一个产品,则可以使用主要升级。这样,用户只能安装一个版本,只有一个版本的程序集。

并排安装的版本化组件仅适用于不同的产品。

  

决定由于错误修复是唯一的改变,我们会这样做   将策略文件添加到GAC,这将重定向Foo的引用   2.0.0到Foo 2.0.1。此策略文件已添加到安装程序中   新功能内部的新组件。

这是一个黑客,很可能是导致问题的原因。您的新安装应该与Foo 2.0.0一起卸载旧版本。

主要升级应始终是独立的。