Windows Installer手引書 Part.33 WiX Bundle

[**前の記事へ**](https://qiita.com/tohshima/items/4c4e293c87b937ca5f14)　　[**目次へ**](https://qiita.com/tohshima/items/dc4c4721d50a2ad70c7a)　　[**次の記事へ**](https://qiita.com/tohshima/items/6f7a5e533824bf4f48f5)

## 複数の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:Bundle.wxs
<?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>
```

例えばここから、２つのMSIファイルを一度にインストールするPackage Bundleを作るのは容易です。Bundleエレメントの要素に製品名やバージョンなどを設定し、Chainエレメント内に2つのMsiPackageエレメントを置くだけです。

```xml:Bundle.wxs
<?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](https://wixtoolset.org/documentation/manual/v3/bundle/wixstdba/)

執筆時点で、例示した「WixStandardBootstrapperApplication.RtfLicense」と合わせて５種類選択できます。この記事では、UIのカスタマイズには触れずに先に話を進めます。

## 親インストーラーが「アプリと機能」に登録される

前節で例示したインストーラーを使用すると、設定の「アプリと機能」に親インストーラーである`Part33_01`だけが表示され、子インストーラーである`Part33_a`と`Part33_b`は表示されません、レジストリを確認すると`Part33_a`と`Part33_b`の項目はあるのですが非表示になっています。これを、表示されるように親インストーラーを構成することができます。MsiPackageエレメントに属性`Visible="yes"`を追加すれば表示されるようになります。

```xml
<Chain>
    <MsiPackage Id="msipkg_a" SourceFile="Part33_a.msi" Visible="yes" />
    <MsiPackage Id="msipkg_b" SourceFile="Part33_b.msi" Visible="yes" />
</Chain>
```

インストール後、「アプリと機能」には、以下のように３つの項目が表示されます。残念ながら（というかそんな機能はないので当たり前ですが）、これを見ても、`Part33_a`と`Part33_b`が`Part33_01`の子インストーラーであることはユーザーにはわかりません。
![Part33_AppAndFunc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83170/4dc0c465-a2bd-dbbc-e3dd-992cbc581abc.png)
このフラットな表示のされ方を見て、「Part33_01は邪魔。非表示にしよう！」などと思ってはいけません[^1]。なぜなら、`Part33_01`を削除する手段がなくなってしまうからです。`Part33_a`と`Part33_b`を消しても`Part33_01`はレジストリに残ります。インストールに使用したインストーラーが残っていれば、もう一度起動してアンインストールできますが、ユーザーの手元に残っていることを期待はできないでしょう。

ここまで説明したように、「アプリと機能」の製品名表示が不適切なため、MsiPackageエレメントで`Visible`属性は付けては（子インストーラーを表示しては）いけないと思います。また、**親インストーラーの項目を「アプリと機能」に表示したくないなら、WiX Bundleを使うべきではありません。**

## WiX Bundleは子インストーラーとしてのMSIを共有管理できる

おそらく、これがWiX Bundleを使用する最も強い動機だと思います。同じMSIを子インストーラーに持つ２種類の製品をインストールした時、一方の製品をアンインストールしても、もう一方の製品が残っていれば、そのMSIはアンインストールされません。実際に試してみます。下図のような構成の２つの製品を用意します。２つの製品は、Part33_a.msiを共有しています。
![Part33_Share2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83170/516006f9-bc42-a63c-fcd4-90772ff371df.png)
あえて子インストーラーも「アプリと機能」に表示できるようにして、両者をインストールすると下図のようになります。
![Part33_ShareMSI1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83170/5379e880-fde5-d3e6-3fa6-d5db2590e291.png)
ここで、Part33_01をアンインストールすると、下図のようになります。
![Part33_ShareMSI2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83170/ba003654-1f5e-df19-ad0f-d34afd04394a.png)
共有しているPart33_aが無事残っていることが確認できます。そして、Part33_02をアンインストールすれば、Part33_a、Part33_cの両方が削除されます。
![Part33_ShareMSI3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83170/70ab595b-0cc6-ef12-2eb7-295f73809332.png)
繰り返しますが、実験のために子インストーラーを「アプリと機能」に表示しましたが、製品では子インストーラーを表示すべきではありません。


[**前の記事へ**](https://qiita.com/tohshima/items/4c4e293c87b937ca5f14)　　[**目次へ**](https://qiita.com/tohshima/items/dc4c4721d50a2ad70c7a)　　[**次の記事へ**](https://qiita.com/tohshima/items/6f7a5e533824bf4f48f5)

[^1]: BundleエレメントのParentName属性を指定すると、私の環境ではWiX Bundleで作った製品項目が「アプリと機能」で非表示になってしまいます。[WiXのドキュメント](https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html)では、ここで設定した名前が製品名に追加されるような説明になってるんですけどねぇ。