Instalator w pliku msi część 6 – upgrade

W poprzednich częściach o WiX:

Bardzo ważnym zagadnieniem jest aktualizowanie już zainstalowanej aplikacji. Przy pomocy WiX można budować patch, hotfix oraz major upgrade. W tym poście pokaże jak zbudować aktualizację typu major upgrade, która polega na odinstalowaniu pakietu i zainstalowaniu nowego.

<Upgrade Id="$(var.UpgradeCode)">
   <UpgradeVersion Minimum="$(var.ProductVersion)"
      IncludeMinimum="no"
      OnlyDetect="yes"
      Language="1045"
      Property="NEWPRODUCTFOUND" />
   <UpgradeVersion Minimum="0.0.1.0"
      IncludeMinimum="yes"
      Maximum="$(var.ProductVersion)"
      IncludeMaximum="no"
      Language="1045"
      Property="UPGRADEFOUND" />
</Upgrade>
<CustomAction Id="PreventDowngrading" Error="Najnowsza wersja jest już zainstalowana." />
<InstallExecuteSequence>
   <Custom Action="PreventDowngrading" 
      After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
   <RemoveExistingProducts After="InstallFinalize" />
</InstallExecuteSequence>
<InstallUISequence>
   <Custom Action="PreventDowngrading"
      After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
</InstallUISequence>

Element UpgradeVersion, służy do sprawdzenia czy w systemie nie jest już zainstalowany pakiet o takiej wersji jak aktualnie uruchomiony, w takim wypadku zostanie ustawiona właściwość NEWPRODUCTFOUND. Drugi element UpgradeVersion odpowiada za znalezienie poprzednich wersji aplikacji i ustawienie właściwości UPGRADEFOUND. Ważne jest ustawienie atrybutu Language, gdyż będziemy wyszukiwać instalatorów w odpowiednim języku.

Akcja o Id PreventDowngrading, odpowiada za wyświetlenie komunikatu błędu w przypadku, gdy zainstalowana już jest najnowsza wersja aplikacji. Do przebiegu procesu instalacji dodałem wyświetlenie informacji w przypadku gdy jest zainstalowana najnowsze wersja poprzez osadzenie elementu Custom w elemencie InstallExecuteSequence. Drugim osadzonym elementem jest RemoveExistingProducts, który odpowiada za usunięcie starszej wersji aplikacji. Dodatkowo zdefiniowany atrybut After, z wartością InstallFinalize zapewnia, że stara wersja zostanie usunięta dopiero po zainstalowaniu nowej. Dodałem wywołanie akcji PreventDowngrading zabraniającej instalacji starszej wersji w wypadku gdy zostanie uruchomiona instalacja z interfejsem użytkownika.

Pliki konfiguracyjne

Powyższe rozwiązanie spowoduje również utratę wszystkich informacji zawartych w plikach konfiguracyjnych. Pliki .config zostaną usunięte i zapisane wersje z instalatora.

Istnieje sposób na obejście tego problemu, tylko trzeba się o to zatroszczyć już przy tworzeniu pierwotnego instalatora, który później będzie aktualizowany. Każdy plik .config musi zostać umieszczony w osobnym komponencie a atrybut KeyPath musi być ustawiony na wartość True. Spowoduje to, że windows Installer będzie używał daty ostatniej modyfikacji w nowym i starym instalatorze, jeśli się będą różnić nie będzie nadpisywał pliku.

Ostatnim krokiem jest zmiana miejsca, w którym wykonuje się akcja RemoveExistingProducts, należy zmienić wartość atrybutu After na InstallFiles. Po tej zmianie wpierw zostaną zainstalowane wszystkie nowe pliki zanim zostaną usunięte stare. Ponieważ ustawiłem KeyPath na true, liczba referencji do plików .config po zainstalowaniu nowej wersji będzie ustawiona na 2. Po odinstalowaniu starej wersji zostanie zmniejszona do 1, a nie do 0, więc plik nie zostanie usunięty. I o to chodziło.

Gdy nie przewidziałeś aktualizacji plików .config na samym początku trzeba się nieźle nakombinować żeby później dokonać aktualizacji, o czym przekonałem się na własnej skórze.

Sama aplikacja też musi być przygotowana do obsługi starego pliku konfiguracyjnego ? np.: inny format sekcji czy nawet brak całych sekcji(wstawianie wartości domyślnych).

Więcej na ten temat w poście Aarona Stebnera, z którego skorzystałem podczas pisania akapitu o plikach konfiguracyjnych.

Leave a Reply

Your email address will not be published. Required fields are marked *