Lesson 4 アップグレードとモジュラー化
2. 自分自身を置き換える
もし私たちの意図がメジャー・アップグレード、つまり、前のバージョンを完全かつ自動的に削除して新しいバージョンを入れる、 というものである場合、必要なことは、OnlyDetect を no に設定することと、バージョン番号をそれに応じたものに変更することだけです。 このとき Minimum は現在のバージョンによって置き換えることを許す最初のバージョンを指定します (この最小値は 範囲に含めます)が、Maximum は現在のバージョン番号を指定することが出来ます (ただし範囲には含めません)。 このようにすると、最初のバージョンから、現在の一つ前のバージョンまでのすべてのものが、 現在のバージョンをインストールするときに自動的に削除されます。 この同じインストーラを最初に使うインストーラとして使用することも出来る、ということにも注意してください。 前のバージョンを見つけた場合は、前のバージョンを削除して現在のものをインストールします。 しかし、クリーンなシステムで起動された場合は、単に現在のバージョンのアプリケーションをインストールするだけです。 アップグレードのインストーラとフルセットのインストーラを個別に作る必要はありません。
前のバージョンの削除は完全に自動的に行われます。 どんな理由であれ、前のバージョンが削除される時に何らかの操作をする必要がある場合は、 UPGRADINGPRODUCTCODE プロパティを条件にしたカスタム・アクションを書いて対応することが出来ます。 Windows Installer は、自動的な削除が行われるときにだけ、このプロパティを設定します。 プログラムの追加と削除によってアプリケーションが手作業で削除される場合には、このプロパティを設定しません。
Upgrade と UpgradeVersion は、ともに、メジャー・アップグレードでしか働かないことに注意してください。
訳註:本文では言及されていませんが、メジャー・アップグレードでは、RemoveExistingProducts カスタム・アクションを InstallExecuteSequence の中にスケジュールする必要があります。実際、そうしないと、コンパイルが通りません。
SDK ドキュメントによれば、RemoveExistingProducts をスケジュールするタイミングとしては、以下の四つの選択肢があります。 すなわち、(1) InstallValidate の後で、InstallInitialize の前、(2) InstallInitialize の直後、 (3) InstallExecute または InstallExecuteAgain の後で、InstallFinalize の前、そして、 (4) InstallFinalize の直後の四つです。ドキュメントには、第四の位置が最も効率的であると述べられています。
(3) と (4) の場合は、新バージョンをインストールした後に旧バージョンをアンインストールします。 このとき、新旧ともに同一のパスを持つファイルが有る場合は、インストール時には上書きで更新し、アンインストール時には削除しないようにします。 このことを Windows Installer はコンポーネントに対する参照カウントを使うことによって実現しています。 従って、メジャー・アップグレードにおいても、コンポーネントの一貫性は非常に重要です。 同一名のファイルを持つコンポーネントの GUID を変更したり、逆に、 含まれているファイルの名前を変更したのにも関わらずコンポーネントの GUID を以前と同じままにしたりすると、 コンポーネントに対する参照カウントと実際のファイルとの関係に食い違いが生じて、 インストールしたはずのファイルがインストールされていなかったり、 削除した筈のファイルが孤児となって残っていたりする結果になることがあります。
前章で取り上げられたスモール・アップデートおよびマイナー・アップグレードが、作成においても使用においても、 いろいろと厄介な問題がある形式だということを考えると、プログラムの更新を配布する最も手軽で現実的な方法は、 ここで説明されているメジャー・アップグレードであると言って良いでしょう。 ただし、旧バージョンから新バージョンへの移行時にどうやってユーザー・データを保護するか、という問題は残ります。
なお、前章で説明された「セイフティー・ロック」機構は、メジャー・アップグレードでは有効に機能します。 本文では、自分より古いバージョンを探して置き換える、ということだけをやっていますが、 自分より新しいバージョンが見つかればメッセージを表示して動作を中止する、ということも積極的に行うべきでしょう。 ただし、「自分自身と同じバージョンが既にインストールされている場合にアップグレードを中止する」という機能は、実装しても働きません。 その場合は、Package の GUID が同じなので、メンテナンス・モードで動作することになり、バージョンの比較は行われません。
前章の日本語版サンプル Sample-4-1-Upgrade.zip に、 メジャー・アップグレードのサンプルを含めていますので、参照してください (ビルドするためには、WixUtilExtension をリンクする必要があります)。