** Kesken ** ====== Paketointi ja rekisteriasetukset ====== Tässä ohjeessa yritetään selvittää, miten ihmeessä suhtautuvat toisiinsa Windows Installer, Windowsin rekisteri, MSI-paketti, component:ien KeyPath-arvot, ALLUSERS-property, assigned-, published-, advertised-, per-user- ja per-machine-asennukset, tiedostotyypit, Kuun asento ja kananluiden helistely sekä vaikuttavatko kaksi viimeistä loppujen lopuksi mitenkään MSI-paketointiin. Käsittelemme pääasiassa Windows XP:tä, mutta olennaiset asiat ovat toki samoja myös Windows 2000:n osalta. Eroja on XP:n ja 2000:n välillä on esimerkiksi regedit.exe:n kyvyissä; 2000:ssa on tiettyhin asioihin käytettävä ohjelmaa regedt32.exe. Aloitamme lyhyellä katsauksella Windowsin rekisteriin. ===== Windowsin rekisteri ===== Windowsin rekisteri koostuu käytännössä kahdesta osasta, - ''HKEY_LOCAL_MACHINE'' eli ''HKLM'' (koneen asetukset) ja - ''HKEY_USERS'' eli ''HKU'' (käyttäjien asetukset). Näitä rekisterin osia vastaavia tiedostoja kutsutaan ''hive'':iksi ja ne löytyvät seuraavista hakemistoista ^ Rekisterihaara ^ Hakemisto ^ Hive-tiedostot ^ ^ ''HKLM'' | ''%systemroot%\System32\config\'' | ''SAM'' | | || ''SECURITY'' | | || ''SOFTWARE'' | | || ''SYSTEM'' | ^ ''HKU'' | ''%homedrive%\Documents and Settings\//profiili1//'' | ''NTUSER.DAT'' | | | ''%homedrive%\Documents and Settings\//profiili2//'' | ''NTUSER.DAT'' | | | ... | ''NTUSER.DAT'' | Windows kuitenkin tarjoilee rekisteriin useampia "näkymiä", jotka näkyvät vaikkapa Registry Editorin (''regedit.exe'') kautta: * ''HKEY_USERS'' (''HKU'') sisältää kaikkien käyttäjien rekisterit, mutta kirjautuneen käyttäjän rekisteriin päästään aina käsiksi rekisterihaarasta ''HKEY_CURRENT_USER'' eli ''HKCU''. * ''HKEY_CLASSES_ROOT'' eli ''HKCR'' koostetaan rekisterin haaroista * ''HKLM\SOFTWARE\Classes'' ja * ''HKCU\Software\Classes'' siten, että jos sama arvo on molemmissa paikoissa, käytetään ''HKCU''-haaran asetuksia. Lisäksi Windows Installer ja ohjelmat itse työntävät lusikkansa tähän soppaan ja hämmentävät niin ettei soppa tahdo paketoijan lautasella pysyä. ===== KeyPath ===== Kun Windows Installer käynnistää ohjelman (eli kun käyttäjä käynnistää ohjelman esimerkiksi Windows Installer -pikakuvakkeesta), vertaa Windows Installer MSI-cachessa olevaa MSI-pakettia ja koneella vallitsevaa tilannetta siten, että kunkin component:in keypath-arvo tarkastetaan. Jos keypath ei vastaa MSI-paketissa määriteltyä arvoa, tulkitaan kyseinen component rikkinäiseksi ja se "korjataan" eli kirjoitetaan koko component:in sisältö uudelleen koneelle. Tätä tapahtumaa kutsutaan nimillä self-repair tai self-healing, mutta oletattavasti myös nimityksiä "Mitä helvettiä tämä kone nyt tekee?!" ja "Voi &#%*!" on käytetty. Self-repair on kuitenkin oikeasti hyödyllinen ominaisuus ja toivottu toimenpide, kun esimerkiksi käyttäjä käynnistää ohjelman ensimmäistä kertaa ja häneltä puuttuvat MSI-paketissa määritellyt ''HKCU''-rekisterihaaran arvot. Lisäksi huolimattomasti tehty paketti muistuttaa ylläpitäjää tehdyistä virheistä tässä muodossa. Windows Installer edellyttää, että jokaisella component:illa on keypath. Jos keypath-arvoa ei ole erikseen määritelty, käytetään sellaisena MSI-paketin ''Component''-taulun ''Directory_''-sarakkeessa olevaa hakemistoa. Otetaanpa esimerkkinä kuvitteellisen ohjelman "Foo" MSI-paketti, joka alla olevassa kuvassa on avattu Orcalla ja valittu ''Component''-taulusta ''regcomponent1'':lle määritelty ''KeyPath''-sarakkeen arvo ''registry1''. {{ohjeet:foo100-regkeypath.png}} ''Attributes''-sarakkeen arvo 4 taas kertoo, että kyseessä on rekisteriarvo. ^ Bit flag name ^ Decimal ^ Hexadecimal ^ Remote execution option ^ | msidbComponentAttributesRegistryKeyPath | 4 | 0x0004 | If this bit is set, the value in the KeyPath column is used as a key into the Registry table.\\ If the Value field of the corresponding record in the Registry table is null, the Name field in that record must not contain "+", "-", or "*". For more information, see the description of the Name field in Registry table.\\ Setting this bit is recommended for registry entries written to the HKCU hive. This ensures the installer writes the necessary HKCU registry entries when there are multiple users on the same machine. | ''Keypath''-arvo ''registry1'' löytyy siis ''Registry''-taulusta, joka on avattuna alla olevassa kuvassa. {{ohjeet:foo100-regtable.png}} Sarakkeen ''Root'' arvo 0 tarkoittaa, että rekisterimuutos tehdään ''HKCR''-haaraan siten, että jos kyseessä on per-user -asennus, muutetaan ''HKCU\Software\Classes'' hiveä ja jos taas per-machine -asennus niin muutetaankin ''HKLM\Software\Classes'' hiveä. Alla on listattu kaikki mahdolliset arvot. ^ Constant ^ Hexadecimal ^ Decimal ^ Root key ^ | (none) | - 0x001 | -1 | If this is a per-user installation, the registry value is written under HKEY_CURRENT_USER.\\ If this is a per-machine installation, the registry value is written under HKEY_LOCAL_MACHINE. Note that a per-machine installation is specified by setting the ALLUSERS property to 1. | | msidbRegistryRootClassesRoot | 0x000 | 0 | HKEY_CLASSES_ROOT\\ When using Windows 2000 or later, the installer writes or removes the value from the HKCU\Software\Classes hive during per-user installations.\\ When using Windows 2000 or later operating systems, the installer writes or removes the value from the HKLM\Software\Classes hive during per-machine installations. | | msidbRegistryRootCurrentUser | 0x001 | 1 | HKEY_CURRENT_USER | | msidbRegistryRootLocalMachine | 0x002 | 2 | HKEY_LOCAL_MACHINE | | msidbRegistryRootUsers | 0x003 | 3 | HKEY_USERS | ==== Varoituksen sananen ==== Rekisteriasetusten osalta on syytä olla varsin huolellinen, miten ne määrittelee MSI-pakettiin, ryhmittelee component:eihin ja asettaa keypath-arvot. Huolimattomalla paketoinnilla voi päätyä esimerkiksi tilanteeseen, jossa eri paketit yrittävät vuorotellen aina käynnistettäessä korjata omasta mielestään "rikkoutuneita" component:eja. Erityisesti tiedostotyyppien assosioinnissa eri ohjelmille on oltava tarkkana. Otetaanpa esimerkki, jossa meillä on kaksi ohjelmaa, sanotaan Foo ja Bar, ja näiden MSI-paketeissa on määritelty **''Registry''**-taulussa seuraavat rekisteriasetukset ^ Ohjelma ^ Registry ^ Root ^ Key ^ Value ^ Component_ ^ ^ Foo | FooReg1 | 0 (HKCR) | .txt | Foo.textfile | FooComponent1 | ^ Bar | BarReg1 | 0 (HKCR) | .txt | Bar.textfile | BarComponent1 | ja **''Component''**-taulu näyttää vastaavasti seuraavanlaiselta: ^ Ohjelma ^ Component ^ KeyPath ^ ^ Foo | FooComponent1 | FooReg1 | ^ Bar | BarComponent1 | BarReg1 | Kun ohjelma Foo asennetaan, se muuttaa ''.txt''-tiedostopäätteen itselleen. Tämän jälkeen asennetaan ohjelma Bar, joka tekee saman. Kun ohjelma Foo sitten käynnistetään, Windows Installer toteaa asennuksen olevan rikki ja muuttaa ''.txt''-tiedostopäätteen itselleen. Ohjelmaa Bar käynnistettäessä käy samalla tavalla. Jos käyttäjä käy itse muuttamassa ''.txt''-tiedostopäätteen jollekin kolmannelle ohjelmalle, säilyy tämä muutos tasan niin kauan kunnes Foo tai Bar jälleen käynnistetään. Keypath -arvot ovat vaarallisia myös silloin, kun ohjelma itse käyttäjän administrator-oikeuksien avustamana haluaa muuttaa keypath-arvolla varustetun component:in sisältämiä rekisteriasetuksia. Mikä siis oli tarinan opetus? Tutustutaanpa vielä hieman Published- ja Assigned-asennustyypeihin ja niihin olennaisesti liittyvään Windows Installerin ALLUSERS-propertyyn ja jätetään opetus vielä vähän tuonnemmaksi. (Oikeasti yritän vain luetuttaa koko dokumentin.) ===== ALLUSERS ===== Windows Installer tuntee propertyn ALLUSERS. Tällä propertylla voidaan ohjata asennuksen toimintaa käytettäessä "kliksutteluasennusta". Kun käytetään jotain ohjelmistojen jakelujärjestelmää, kuten vaikkapa active directoryn group policyt, ei ALLUSERS-propertyn määritteleminen MSI-pakettiin ole tarpeellista. ALLUSERS-parametri voi olla määriteltynä MSI-paketin ''Property''-taulussa tai se voidaan antaa (korvaten myös paketissa mahdollisesti määritelty arvo) asennuksen yhteydessä komentoriviltä: ''msiexec /i foo.msi ALLUSERS=1'' tai ''msiexec /i foo.msi ALLUSERS=""''. ALLUSERS-property määrittelee, tehdäänkö tai yritetäänkö tehdä niin sanottu "Per-user" vaiko "Per-machine" -asennus. Ohjelmaa asentavan käyttäjän oikeuksilla on ratkaiseva merkitys, kuten alla olevasta taulukosta nähdään. ^ Käyttäjän oikeustaso ^ ALLUSERS = NULL ^ ALLUSERS = 1 ^ ALLUSERS =2 ^ | User | Per-user -asennus. Käytetään käyttäjän profiilin hakemistoja. | Ei toimi. Ei riittäviä oikeuksia. | Per-user -asennus. Käytetään käyttäjän profiilin hakemistoja. | | Administrator | Per-user -asennus. Käytetään käyttäjän profiilin hakemistoja. | Per-machine -asennus. Käytetään "All Users" profiilia. | Per-machine -asennus. Käytetään "All Users" profiilia. | Ja todetaanpa vielä toistamiseen, että kun käyetään jotain ohjelmistojen jakelujärjestelmää, kuten vaikkapa active directoryn group policyt, ei ALLUSERS-propertyn määritteleminen MSI-pakettiin ole tarpeellista tai edes merkityksellistä. Ohjelmistojen jakelujärjestelmä kyllä huolehtii ihan itse, onko kyseessä Per-user vaiko Per-machine -asennus. ===== Per-user ja per-machine ===== ===== Published-, assigned ja advertised -asennukset ===== ===== Tarinan opetus ===== Noudattamalla seuraavia periaatteita vältät pahimmat ongelmat kääriessäsi rekisteriasetuksia pakettiin: * Ohjelman omia rekisteriasetuksia, eli sellaisia joiden myöhemmästä ylikirjoittumisesta ei ole pelkoa, sisältävät component:it voi huoletta varustaa keypath-arvolla. * ''HKCU''-haaraan haluttavia rekisteriasetuksia sisältävät component:it pitää varustaa keypath-arvolla, jotta rekisteriasetukset luotaisiin käyttäjän käynnistäessä ohjelmaa ensimmäistä kertaa. * Yleisiä rekisteriasetuksia, kuten tunnettuja tiedostopääte- ja protokolla-assosiointeja lisättäessä ei kyseisiin component:eihin kannata laittaa keypath-arvoa. On myös mahdollista tehdä MSI-paketista hieman "kiltimpi" käyttämällä component:issa seuraavaa attribute-arvoa: ^ Bit flag name ^ Decimal ^ Hexadecimal ^ Remote execution option ^ | msidbComponentAttributesNeverOverwrite | 128 | 0x0080 | If this bit is set, the installer does not install or reinstall the component if a key path file or a key path registry entry for the component already exists. The application does register itself as a client of the component.\\ Use this flag only for components that are being registered by the Registry table. Do not use this flag for components registered by the AppId, Class, Extension, ProgId, MIME, and Verb tables. | ([[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/database_tables.asp|Component Tablen kuvaus MSDN:ssä]])