Принудительное обновление файла, который был изменен во время первоначальной установки

Я работаю над функцией обновления для моего установщика на основе WiX.

В рамках установки мы устанавливаем файл web.config, а затем используем настраиваемое действие для обновления строк подключения внутри файла.

Но это вызывает проблему, когда мы запускаем наше обновление. Мы бы хотели, чтобы RemoveExistingProducts был запланирован после InstallFinalize, поскольку это наиболее эффективно с точки зрения не удаления и повторной установки файлов, которые не были изменены. Но это оставляет оригинальный файл web.config на месте, когда установщик Windows пытается определить, следует ли ему обновить его или нет. Поскольку дата его последнего изменения более поздняя, ​​чем дата его создания, установщик Windows решает не обновлять его (см. Правила управления версиями, которые использует установщик Windows). Но нам нужно, чтобы оно было обновлено.

Одним из очевидных решений является изменение расписания RemoveExistingProducts на после InstallValidate - но это неэффективно, а также, я не думаю, что это даст нам возможность перенести настройки из существующих файлов, если нам потребуется это сделать.

Есть другие идеи?

3 ответа

Решение

Есть много способов - ни один не идеален.

1: Вы можете использовать сопутствующий файл для принудительного обновления соответствующего файла. При условии, что указанный сопутствующий файл всегда обновляется, это может быть путь. По сути, это означает, что вы связываете не версионный файл с логикой обновления версии его сопутствующего файла (файлы обновляются вместе). Я никогда не использовал это в WIX, но я думаю, что это так же просто, как добавить атрибут CompanionFile к элементу File и указать идентификатор файла, который вы хотите "version follow". Внутри MSI-файла это будет выглядеть примерно так:

введите описание изображения здесь

2. Вы можете использовать настраиваемое действие для удаления файла до его оценки (или, что еще лучше, переименовать его в резервный формат). Проблема в том, что в случае сбоя установки файл будет отсутствовать. Если вы переименуете файл вместо удаления, вы можете вернуть его обратно в случае сбоя установки через пользовательское действие отката. Иногда я использую таблицу RemoveFile для удаления файлов при установке, но в зависимости от последовательности, указанной в InstallExecuteSequence, это может не сработать (удаление должно произойти до того, как msi выполнит оценку стоимости файла).

3: Тогда есть подход кувалдой: набор REINSTALLMODE = amus заставить перезаписать все файлы независимо от версии. Я не должен даже упоминать об этом, поскольку это ужасно опасно (вы можете в конечном итоге перезаписать системные файлы или в более новых версиях Windows вызвать неприятную ошибку времени выполнения, так как файлы защищены). Используйте его только для тестирования разработчиков, и не думайте, что это быстрое решение. Это вызывает больше проблем, чем решает.

Как вариант, приемлемым подходом может быть установка REINSTALLMODE на emus (замена файлов старой и той же версии). Это может помочь, если вы не хотите увеличивать номера версий, но продолжаете перестраивать свои двоичные файлы - как это имеет место во многих.NET. Я предполагаю, что это вызовет целый ряд новых проблем - наиболее существенно бинарные, но идентичные версии файлов в дикой природе, если вы используете его для публичных выпусков - запах развертывания, если когда-либо был. Как только подход QA/DEV, он может работать. А если серьезно, зачем? Просто автоматически увеличьте версию сборки двоичных файлов, и проблема будет решена надежно.


Ссылки:

Только сомнительные. Вы можете удалить конкретный файл на ранней стадии с помощью специального действия, но обязательно сделайте это правильно! Или вы можете указать версию файла, чтобы правила обновления рассматривали его как замену файла без версии файлом с версией, но тогда исправления могут помешать неправильной версии этого файла.

Не используйте настраиваемое действие для обновления вашего конфигурационного файла - другая очевидная идея. Вместо этого получите WIX, чтобы выполнить обновление через расширения XML. Например

<Component Id="web.config" Guid="f12ff575-ad5f-47bc-a5c9-40b1e3a7f9f5" >
    <File Source="$(var.SrcPath)\web.config.config" KeyPath="yes" />

    <util:XmlConfig Id="AppSqlInstanceName"
                    File="[#web.config]"
                    Action="create"
                    ElementPath="//configuration/connectionStrings/add[\[]@name='YourStringKey'[\]]"
                    Name="connectionString"
                    Node="value"
                    Value="metadata=res://*/YourModel.csdl|res://*/YourModel.ssdl|res://*/YourModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=[SQLSERVERANDINSTANCE];initial catalog=DatabaseName;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;"
                    On="install"/>
</Component>

Для этого используется переменная [SQLSERVERANDINSTANCE], которую необходимо настроить перед запуском.

Другие вопросы по тегам