@ledsun blog

無味の味は佳境に入らざればすなわち知れず

メジャー・アップグレードでのUpgrade要素の役割

WiX チュートリアル 日本語訳 Lesson 4 アップグレードとモジュラー化 / 1. 古いのを探す の Sample-4-1-Upgrade.zip に含まれる SampleMajorUpgrade.wxs を参考にして話を進めます。 メジャー・アップグレードでは次のように Upgrade要素 を定義します。

<Upgrade Id='YOURGUID-7349-453F-94F6-BCB5110BA4FD'>
  <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
                  Minimum='1.1.0' IncludeMinimum='no' />
  <UpgradeVersion OnlyDetect='no' Property='PREVIOUSFOUND'
                  Minimum='1.0.0' IncludeMinimum='yes'
                  Maximum='1.1.0' IncludeMaximum='no' />
</Upgrade>

この中の UpgradeVersion要素が表すものがよくわかりませんでした。 2つ似たような書き方をしていますが、役割は異なります。

古いバージョンの削除

後ろの要素から説明します。 メジャー・アップグレードでは、新しいバージョンのコンポーネントをインストールしてから、古いバージョンのコンポーネントを削除します。 このUpgradeVersion要素は、削除対象のコンポーネント(を含むProduct)を探す条件を指定しています。

  <UpgradeVersion OnlyDetect='no' Property='PREVIOUSFOUND'
                  Minimum='1.0.0' IncludeMinimum='yes'
                  Maximum='1.1.0' IncludeMaximum='no' />

見つかったProductに含まれるコンポーネント<RemoveExistingProducts After="InstallFinalize" /> で削除されます。

UpgradeやUpgradeVersionという名前の割に削除するコンポーネントを探すのが少し不思議な感じします。 Upgrade要素の名前はWindowsインストーラーのUgradeテーブル から来ています。

システムにインストールされている影響を受ける製品が Find関連製品 のアクションによって検出されると、actionproperty 列に指定されたプロパティに製品コードが追加されます。 Removeexistingproductsアクションとmigratefeaturestatesアクションでは、actionproperty 列に記載されている製品のみが削除または移行されます。

とあるように、UpgradeVersion要素で指定した条件で見つかったProductはUpgradeテーブルに追加されます。 Removeexistingproductsアクションに対応した<RemoveExistingProducts After="InstallFinalize" /> で削除されます。 Upgrade要素はUpgradeテーブルそのままです。

ちなみにProperty='PREVIOUSFOUND'が指定されていますが、このプロパティ名は特に使われません。 好きな名前をつけてかまいません。ただPropertyは必須属性なので*1何かしら設定する必要はあります。

新しいバージョン

前者はインストールしたいバージョンより新しいバージョンの条件を指定します。

  <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
                  Minimum='1.1.0' IncludeMinimum='no' />

これもUpgradeテーブルを使うのですが、趣が少し違います。

古いパッケージが新しいバージョンでインストールできないようにする - Win32 apps | Microsoft Docs

  1. アップグレードテーブルの [属性列に msidbUpgradeAttributesOnlyDetect ビットフラグを入力します。
  2. このパッケージによって提供されるアップグレードのバージョンを、 アップグレードテーブルの VersionMin 列に入力します。 VersionMax 列を空白のままにします。
  3. Findrelatedproducts アクションによって設定されるプロパティの名前を、アップグレードテーブルの actionproperty 列に入力します。
  4. アップグレードテーブルの actionproperty 列で、 SecureCustomPropertiesプロパティとという名前のプロパティを プロパティテーブルに追加します。
  5. Installexecutesequence テーブルの Findthe findproducts アクションの後に、カスタムアクションの種類 19を追加します。 このアクションの CustomAction テーブル にレコードを含め、ターゲット列に表示されるテキストを入力します。 Type 19 カスタムアクションはインストーラーに組み込まれているので、記述するコードはありません。

この手順のための定義です。 2のために、OnlyDetect='yes'を定義します。 3のために、Property='NEWERFOUND'を定義します。 6のために、次のようなアクションを定義します。

<Custom Action='WixExitEarlyWithSuccess' After='FindRelatedProducts'>NEWERFOUND</Custom>

WixExitEarlyWithSuccessの実体は次のようなカスタムアクションです。

<CustomAction Id="WixExitEarlyWithSuccess" Error="新しいバージョンが既にインストールされているためインストールできません。" />

CustomAction Element

This attribute specifies an index in the MSI Error table to use as an error message for a type 19 custom action that displays the error message and aborts a product's installation.

WiXのカスタムアクション」でError属性を指定すると、「WindowsインストーラーのType 19 カスタムアクション」が使われます。

感想

WiXの定義の仕方はなかなかややこしいのですが、Windowsインストーラーの仕様に起因しているようです。 最終的にはWindowsインストーラーの仕様を読み込むのが良さそうです。