编辑:引用自己,因为我在下面的评论之一中更好地总结了这个问题......
安装软件包时,我的条件是真的,但是 删除时不正确。我希望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>
答案 0 :(得分:1)
在a之后删除孤立的功能/组件是否安全 产品是否已卸载?
不,不是。如果您只是删除它,它的组件注册信息仍保留在机器上。
有没有办法检查什么,如果有的话,仍在引用 我认为是孤儿的一个组成部分?
不是真的。但是,如果有某些内容引用了您的某个组件,则很可能是您开发的另一种产品或当前产品的旧版本未正确卸载。
随机产品不太可能引用您的组件或组件。
如何修复我的安装程序以防止这种情况发生 未来?
使用卸载旧组件的主要升级并安装新组件。没有特殊的政策文件,没有条件安装或删除。
可以在机器上安装多个版本的Foo库 一次,每个都将位于相应的文件夹中 在Foo。
为什么呢?如果您有一个产品,则可以使用主要升级。这样,用户只能安装一个版本,只有一个版本的程序集。
并排安装的版本化组件仅适用于不同的产品。
决定由于错误修复是唯一的改变,我们会这样做 将策略文件添加到GAC,这将重定向Foo的引用 2.0.0到Foo 2.0.1。此策略文件已添加到安装程序中 新功能内部的新组件。
这是一个黑客,很可能是导致问题的原因。您的新安装应该与Foo 2.0.0一起卸载旧版本。
主要升级应始终是独立的。