msi
WiXToolset

WixにおけるFeatureの扱い方の注意

More than 1 year has passed since last update.

はじめに

WixFeatureという機能を調べている途中ではまったポイントがあったのでメモ。

Featureという機能

WixというかMSIにおいて、構成要素の最小単位はコンポーネントだが、個々のコンポーネントをグループ分けして、インストールするかどうかを決める仕組みとして、Featureというものがある。

Wix内で定義する場合、Product要素以下にFeatureを定義して、名前、インストールレベル等を設定すれば、それでMSIの中に登録されることになる。

Featureの選択方法と問題

WixでどのFeatureをインストールするか選択する場合、通常はFeatureTreeや、Advanced、Mondo等、Wix側で用意されたUIを使用して選択する。
しかし、この方法は必ずWix側で用意されたツリー構造で行う必要があり、例えばチェックボックスで制御したい場合等、小回りが利かない部分がある。

もう一つの方法としてWXSファイル内のFeature要素の下にConditionを置けば、プロパティに基づいてインストールの可否を決めてくれるように見える。

Product.wxs
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product...>
    ...
    <Feature Id="TestFeature" Title="TestFeature" Absent="allow" Level="2" Description="TEstTest">
      <!-- TESTPROPERTYが定義されていれば、インストールすることを期待 -->
      <Condition Level="1"><![CDATA[TESTPROPERTY]]></Condition>
      <ComponentRef Id="Component.TextFile1.txt" />
    </Feature>
  </Product>
</Wix>

しかし、上記のwxsでmsiを作成し、インストールを実行すると、 サイレントでプロパティを定義すればTestFeatureがインストールされるが、UI内でプロパティ定義してインストールすると、TestFeatureが入らないという問題が起こる。

原因

MSI内におけるMigrateFeatureStatesというアクションの実行タイミングが関係している。
MigrateFeatureStates自体はIntallUISequenceまたはInstallExecuteSequenceの両方で実行されるが、InstallUISequenceで実行された場合、InstallExecuteSequenceを通っても何もMSIは何も実行しない。

そして、InstallUISequence内では、 ダイアログが表示される前にMigrateFeatureStatesは実行される。
よって、この後にいくら//Feature/Conditionで指定されているプロパティの中身を書き換えようが、インストールされるFeatureは決定しているので、インストールされるFeatureには何も影響を及ぼさなくなる。

回避方法

  • ダイアログシーケンスの中でADDLOCALプロパティを直接編集する
    • カンマ区切りで名前を指定する
  • カスタムアクション内でMsiUseFeatureを使用する
    • C#で使う場合は、DTF(Deployment Tools Foundation)内のMicrosoft.Deployment.WindowsInstaller.Installer.UseFeatureメソッドが使える
  • Installation Package Bundles等のブートストラッパーを使って、MSIインストール実行前にプロパティを設定する(MSI内蔵のUIを使用しない)

前者二つに関しては、Featureが小規模のうちはまだ大丈夫だが、規模が膨れ上がってくると途端に管理が難しくなるので、扱いには注意が必要となる。
ブートストラッパーを使用する場合、場合によっては一からUIを構築する必要があるので、こちらはより大規模アプリ向けの方法となる。

DTFについてはWixのバイナリにchmとdllが同梱されているので、そちらを参照のこと。(公式のオンラインドキュメントが見つからなかった)