Instalator w pliku msi część 2

Po krótkim wstępie teoretycznym w poprzednim artykule w tej części pokażę jak stworzyć swój pierwszy(prosty;)) instalator za pomocą Windows Installer XML.

Po zainstalowaniu Wixa np stąd w Visual Studio pojawi się nowy typ projektu(jeśli używasz jeszcze wersji 2005 nie zapomnij o ProjectAgregator.msi, a najlepiej przerzuć się na 2008):


W tym momencie posłużę się typem Wix Project.

Domyślnie projekt zawiera tylko jeden plik WixProject.wxs:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
        <Product Id="b9351b34-7683-4640-8fdf-dc34c12c3fa1"
             Name="PUT-PRODUCT-NAME-HERE"
             Language="1033"
             Version="1.0.0.0"
             Manufacturer="PUT-COMPANY-NAME-HERE"
             UpgradeCode="077c926e-d3f7-40dd-a6cf-5c5cc82893f2">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="WixProject.cab" EmbedCab="yes" />

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="PUT-APPLICATION-DIRECTORY-HERE">

                    <Component Id="ProductComponent" Guid="ee728cb7-f2b3-41d0-9ea5-59ebf659f8d2">
                        <!-- TODO: Insert your files, registry keys, and other resources here. -->
                    </Component>

                </Directory>
            </Directory>
        </Directory>

        <Feature Id="ProductFeature" Title="PUT-FEATURE-TITLE-HERE" Level="1">
            <ComponentRef Id="ProductComponent" />
        </Feature>
    </Product>
</Wix>

XmlNs

Warto zwrócić uwagę na namespace, ponieważ pozwala szybko określić czy skrypt został utworzony dla wersji 3.0 (http://schemas.microsoft.com/wix/2006/wi), czy 2.0 (http://schemas.microsoft.com/wix/2003/01/wi).

Element Product

Atrybuty wpisane w tym elemencie zapisywane są w tabeli Property i służą do identyfikowania instalatorów. Niektóre są wymagane:

  • Id – unikalny identyfikator instalatora, dla każdej wersji powinien być inny; odpowiada wartości o nazwie ProductCode z tabeli Property
  • Name – nazwa produktu, po prostu jakiś string opisujący Twoją aplikację odpowiada ProductName
  • Language – język, w którym zbudowany jest instalator; jest to kod LCID języka, domyślna wartość to 1033 czyli język angielski; to pole ma znaczenie przy tworzeniu lokalizowanych instalatorów (o tym później); odpowiada ProductLanguage
  • Version – znany z .net symbol wersji w formacie major.minor.build.revision, ciekawostką, jest że .revision jest pomijane; odpowiada ProductVersion
  • Manufacturer – producent oprogramowania, albo twoje imię i nazwisko; odpowiada Manufacturer(tak samo)
  • UpgradeCode – po tym guidzie wyszukiwane są produkty do podniesienia wersji; jeśli tworzysz wiele instalatorów dla różnych wersji i chcesz żeby bezproblemowo można było dokonać upgradu to trzeba pamiętać, że ten GUID powinien pozostać stały. Zapobiega to wielokrotnemu pojawianiu się elementów w Dodaj/Usuń programy w panelu sterowania

Element Package

Wymagane są tylko 2 pola:

  • InstallerVersion – określa wersje wymaganego WindowsInstallera zgodnie z wzorem: major*100 + minor
  • Compressed – określa czy pliki zawarte w instalatorze mają podlegać kompresji

Reszta pól jest dziedziczona z elementu Product. Cała zawartość elementu Package ląduje w strumieniu Summary Information, który może być odczytywany bezpośrednie z windows explorera.

Element Media

Pozwala na podanie zbioru zawierającego instalowane pliki(atrybut Cabinet) i podania czy wejdzie w skład instalatora(EmbedCab). Jeśli nie podamy żadnego z tych elementów instalator nie będzie zawierał plików źródłowych, trzeba je będzie normalnie skopiować do lokalizacji pliku .msi, ale tego byśmy raczej nie chcieli 😉

Element(y) Directory

Służą do określenia struktury folderów, w której ma zostać zainstalowana aplikacja. Poszczególne zagnieżdżenia pokazują jak foldery są tworzone w głąb. Pierwszy wpis( TARGETDIR, SourceDir) jest wirtualny i służy do definiowania korzenia struktury folderów.

W atrybucie ID podaje się nazwę właściwości (pisana w WiX dużymi literami), która może być później używana w innych miejscach w instalatorze. Istnieją predefiniowane wartości parametru ID pozwalające na odwołanie się do standardowych lokalizacji:ProgramFilesFolder, ProgramMenuFolder, DesktopFolder. Pełna lista znajduje się tutaj. Atrybut Id często jest używany do odwołań w innych miejscach, więc należy zadbać żeby był unikalny.

Warto stosować spójny system wartości ID w całym skrypcie np.: wszystkie katalogi nazywać D_NAZWAFOLDERU.

Zalecana struktura folderów to “/Program Files/Firma/Produkt”, chociaż w praktyce spotyka się “/Program Files/Firma Produkt”.

Element(y) Component

Zagnieżdżony w elemencie Directory. To kluczowy element skryptu Wix i najczęstsze źródło błędów podczas instalacji. Komponent jest najmniejszym zestawem “rzeczy”, które mogą zostać zainstalowane: plików, skrótów, rejestrów. W skrypcie może istnieć wiele komponentów, najważniejsze żeby były niezależne:

  • w 2 komponentach nie mogą być zawarte te same pliki w tych samych lokalizacjach
  • odinstalowanie komponentu, nie powinno zostawiać żadnych śmieci,
  • odinstalowanie komponentu nie może mieć wpływu na inne komponenty

Komponenty to klocki z których składami konkretne funkcjonalności, czyli działającą aplikację. Jeden komponent powinien zawierać elementy, które tworzą wspólną całość. Komponenty mogą być współdzielone przez funkcjonalności np.: gdy mamy 2 aplikacje, które obie korzystają z narzędzia do raportowania (np CrystalReports) i wymagają odpowiednich zarejestrowanych bibliotek.

Oczywiście należy zwrócić uwagę na nazewnictwo – pole Id musi być unikalne, ale w miarę proste do użycia w innych miejscach. Ja stosuję nazewnictwo typy C_NazwaKomponentu. Pole Guid musi być unikalne.

Przykładowa zawartość komponentu może wyglądać tak:

<Component Id="C_GlownaAplikacja" Guid="ac45b2d6-7e95-487f-a2e2-f56877f16076">
  <File Id="DetalExe" Name="Detal.exe" Source="$(var.Sln.Path)\Detal\bin\$(var.Conf)\Detal.exe" />
  <File Id="DetalExeConfig" Name="Detal.exe.config" Source="$(var.Sln.Path)\Detal\bin\$(var.Conf)\Detal.exe.config" />
</Component>

Spowoduje to zainstalowanie 2 plików, przy okazji użyłem zmiennych preprocesora, ale w celach testowych można spokojnie hardcodować ścieżki.

Element Feature

Pozwala operować na wyższym poziomie i spiąć komponenty w funkcjonalności(feature). Funkcjonalność to jest to co użytkownik będzie miał dostępne do wyboru podczas instalacji ( o ile będziemy mieli wogóle UI;) ) W atrybucie Title wpisujemy przyjazną nazwę jak np.: aplikacja Detal.

Jako dzieci używamy elementów ComponentRef, które zainstalują odpowiednie komponenty.

Instalator

Omówione elementy to podstawy WiXa z ich pomocą można stworzyć podstawowy instalator Na przykład taki:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
	<Product Id="bda85c5c-a6bb-4212-a213-9fe00ba2d7c4"
           Name="Moja aplikacja" Language="1033" Version="1.0.0.0"
           Manufacturer="bartekszafko.pl" UpgradeCode="6f2d912a-9409-433b-bd5f-bf82ad362291">
		<Package InstallerVersion="200" Compressed="yes" />

		<Media Id="1" Cabinet="WixProject1.cab" EmbedCab="yes" />

		<Directory Id="TARGETDIR" Name="SourceDir">
			<Directory Id="ProgramFilesFolder">
				<Directory Id="INSTALLLOCATION" Name="Moja aplikacja">
					<Component Id="C_MojaAplikacja" Guid="45eee2b7-829c-457b-ab37-ce957f56d1a6">
            <File Id="F_WindowsFormsApplication1" Name="WindowsFormsApplication1.exe"
                  Source="..\WindowsFormsApplication1\bin\Debug\WindowsFormsApplication1.exe" />
          </Component>
				</Directory>
			</Directory>
		</Directory>

		<Feature Id="ProductFeature" Title="Moja aplikacja" Level="1">
			<ComponentRef Id="C_MojaAplikacja" />
		</Feature>
	</Product>
</Wix>

Jako tip: warto dodać do projektu WiX właściwą aplikację jako referencje lub ustawić odpowiedni build order, wtedy zawsze będzie pakować się najnowsza wersja aplikacji.

Po uruchomieniu tak przygotownego pliku .msi będdziemy mogli zobaczyć znajome okienko:

A po wejściu do “Dodaj/usun programy” będzie można usunąć aplikację.

3 thoughts on “Instalator w pliku msi część 2

  1. […] poprzednim artykule zbudowałem podstawowy instalator w MSI za pomocą Windows Installer Xml. Jego wygląd pozostawiał […]

  2. […] poprzednim artykule zbudowałem podstawowy instalator w MSI za pomocą Windows Installer Xml. Jego wygląd pozostawiał […]

  3. Grzegorz Wiśniewski says:

    Witaj,
    Na podstawie tego artykułu stworzyłem taki plik:

    Czyli nic skomplikowanego, a podczas kompilacji uzyskuję następujący błąd:

    Unresolved reference to symbol ‘WixComponentGroup:C_DEMO’ in section ‘Product:{9C2E54E3-D590-437C-AD93-1382D38F675C}’.

    Nie bardzo rozumiem czemu tak się dzieje.

    Pozdrawiam,
    Grzegorz

Leave a Reply

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