编辑:引用我自己的话,因为我在下面的评论之一中更好地总结了这个问题......</p>
我有一个条件,在安装包时为真,但在删除它时不为真。我希望 MSI 记住它已经安装了条件组件并通过卸载将其删除,但事实并非如此。我正在尝试找出 A) 清理此孤立组件的正确方法,以及 B) 将来防止此问题的最佳方法。
我想我的问题归结为,在卸载产品后删除孤立的功能/组件是否安全?有没有办法检查什么(如果有的话)仍在引用我认为是孤儿的组件?以及如何修复我的安装程序以防止将来发生这种情况?
我们有一个 wix 项目来安装库 Foo。默认情况下,此安装程序将 Foo.dll 的副本放入 GAC 和文件夹中Program Files\Reference Assemblies\Foo\<version>
。安装程序还添加了两个注册表项,一个是自定义键,用于存储 Foo 文件夹的路径以供将来安装时重复使用,另一个告诉 Visual Studio<version>
在其搜索已安装库时包含完整文件夹路径,以便 Foo 显示在“添加引用”对话框。可以一次在机器上安装多个版本的 Foo 库,每个版本都位于<version>
Foo 下的相应文件夹中。
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>