複数のMSI形式インストーラーを一つにできるが・・・
WiX ToolsetにはWix Bundleと呼ばれる、exe形式のインストーラーを作成する機能があります。機能的には、複数のMSIファイル(製品)を一度にインストールできるようにするイメージではなく、複数のMSIファイルを一つの製品としてインストールしているように見せるイメージです。WiX Toolsetのドキュメントを見ながら、「こんな機能もあるのねー」などと思いながらカスタムしていくと、リリースした後に困ったことが起きやすい、実は難しい仕組みです。また、Web上を検索しても、細かなチューニングがやりにくい印象があります。インストーラー作成者としては避けたい技術ではあるのものの、Wix Bundleを使わざるを得ないケースもまれにあるので、解説しておきます。
WiX Bundleの作り方
仕組みについて説明する前に、WiX Bundleの作り方を簡単に説明します。XML形式でソースファイルを記述し、candle.exeでコンパイルし、light.exeでリンクするところはMSIの作成方法と同じです。Wix Toolset Visual Studio 20xx Extensionを組み込んだVisual Studioの「新しいプロジェクトの作成」で、Bootstrapper Project for WiX v3を選ぶと、以下のテンプレートが生成されます。
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Name="Part33_01" Version="1.0.0.0" Manufacturer="" UpgradeCode="9b276dae-7f0b-4550-9de4-71a24ef630d7">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- TODO: Define the list of chained packages. -->
<!-- <MsiPackage SourceFile="path\to\your.msi" /> -->
</Chain>
</Bundle>
</Wix>
例えばここから、2つのMSIファイルを一度にインストールするPackage Bundleを作るのは容易です。Bundleエレメントの要素に製品名やバージョンなどを設定し、Chainエレメント内に2つのMsiPackageエレメントを置くだけです。
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Name="Part33_01" Version="1.0.0" Manufacturer="tohshima" UpgradeCode="9b276dae-7f0b-4550-9de4-71a24ef630d7">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Id="msipkg_a" SourceFile="Part33_a.msi"/>
<MsiPackage Id="msipkg_b" SourceFile="Part33_b.msi"/>
</Chain>
</Bundle>
</Wix>
インストールウィザードの見栄えを決めるBootstrapperApplicationRefエレメントのIdに指定できる文字列は、下記のページの説明を読めばわかります。
Working with WiX Standard Bootstrapper Application
執筆時点で、例示した「WixStandardBootstrapperApplication.RtfLicense」と合わせて5種類選択できます。この記事では、UIのカスタマイズには触れずに先に話を進めます。
親インストーラーが「アプリと機能」に登録される
前節で例示したインストーラーを使用すると、設定の「アプリと機能」に親インストーラーであるPart33_01
だけが表示され、子インストーラーであるPart33_a
とPart33_b
は表示されません、レジストリを確認するとPart33_a
とPart33_b
の項目はあるのですが非表示になっています。これを、表示されるように親インストーラーを構成することができます。MsiPackageエレメントに属性Visible="yes"
を追加すれば表示されるようになります。
<Chain>
<MsiPackage Id="msipkg_a" SourceFile="Part33_a.msi" Visible="yes" />
<MsiPackage Id="msipkg_b" SourceFile="Part33_b.msi" Visible="yes" />
</Chain>
インストール後、「アプリと機能」には、以下のように3つの項目が表示されます。残念ながら(というかそんな機能はないので当たり前ですが)、これを見ても、Part33_a
とPart33_b
がPart33_01
の子インストーラーであることはユーザーにはわかりません。
このフラットな表示のされ方を見て、「Part33_01は邪魔。非表示にしよう!」などと思ってはいけません1。なぜなら、Part33_01
を削除する手段がなくなってしまうからです。Part33_a
とPart33_b
を消してもPart33_01
はレジストリに残ります。インストールに使用したインストーラーが残っていれば、もう一度起動してアンインストールできますが、ユーザーの手元に残っていることを期待はできないでしょう。
ここまで説明したように、「アプリと機能」の製品名表示が不適切なため、MsiPackageエレメントでVisible
属性は付けては(子インストーラーを表示しては)いけないと思います。また、親インストーラーの項目を「アプリと機能」に表示したくないなら、WiX Bundleを使うべきではありません。
WiX Bundleは子インストーラーとしてのMSIを共有管理できる
おそらく、これがWiX Bundleを使用する最も強い動機だと思います。同じMSIを子インストーラーに持つ2種類の製品をインストールした時、一方の製品をアンインストールしても、もう一方の製品が残っていれば、そのMSIはアンインストールされません。実際に試してみます。下図のような構成の2つの製品を用意します。2つの製品は、Part33_a.msiを共有しています。
あえて子インストーラーも「アプリと機能」に表示できるようにして、両者をインストールすると下図のようになります。
ここで、Part33_01をアンインストールすると、下図のようになります。
共有しているPart33_aが無事残っていることが確認できます。そして、Part33_02をアンインストールすれば、Part33_a、Part33_cの両方が削除されます。
繰り返しますが、実験のために子インストーラーを「アプリと機能」に表示しましたが、製品では子インストーラーを表示すべきではありません。
-
BundleエレメントのParentName属性を指定すると、私の環境ではWiX Bundleで作った製品項目が「アプリと機能」で非表示になってしまいます。WiXのドキュメントでは、ここで設定した名前が製品名に追加されるような説明になってるんですけどねぇ。 ↩