Условная функция WiX / компонент, потерянный при удалении
Изменить: цитируя себя, потому что я изложил проблему гораздо лучше в одном из комментариев ниже...
У меня есть условие, которое верно, когда пакет установлен, но не верно, когда он удален. Я ожидал, что 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.0 при установке Foo 2.0.1. Установка функции политики была сделана условной при обнаружении 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 ответ
Безопасно ли просто удалить потерянные функции / компонента после удаления продукта?
Нет, это не так. Если вы просто удалите его, информация о регистрации его компонента останется на машине.
И есть ли способ проверить, что, если вообще что-то, все еще ссылается на компонент, который я считаю сиротой?
На самом деле, нет. Но если что-то ссылается на один из ваших компонентов, это, скорее всего, другой продукт, разработанный вами, или более старая версия вашего текущего продукта, которая не была удалена правильно.
Маловероятно, что случайный продукт будет ссылаться на ваш компонент или сборку.
И как мне исправить мой установщик, чтобы предотвратить это в будущем?
Используйте серьезные обновления, которые удаляют старый компонент и устанавливают новый. Никаких специальных файлов политики, никаких условных установок или удалений.
Несколько версий библиотеки Foo могут быть установлены на компьютере одновременно, каждая из которых будет расположена в соответствующей папке под Foo.
Зачем? Если у вас есть один продукт, вы можете использовать крупные обновления. Таким образом, у пользователя будет установлена только одна версия с одной версией вашей сборки.
Версионные сборки, установленные бок о бок, имеют смысл только для разных продуктов.
Было решено, что, поскольку исправление ошибки было единственным изменением, мы добавим в GAC файл политики, который перенаправит ссылки на Foo 2.0.0 на Foo 2.0.1. Этот файл политики был добавлен в программу установки в качестве нового компонента внутри новой функции.
Это взлом, и, скорее всего, именно это является причиной проблемы. Ваш новый установленный должен был удалить старую версию вместе с Foo 2.0.0.
Основные обновления всегда должны быть автономными.