このページはアーカイブされた古いページです。
インストーラ講座の目次へ



Windows インストーラ講座 − Major Upgrade
Major Upgradeを行った場合、それ以前にインストールされた旧メジャーバージョンは削除されません。
これは、Windows インストーラ では、異なるメジャーバージョンのものは、”共存が可能”である事が前提となっているためです。
インストーラーの作成者(=あなた)は、新旧のメジャーバージョンで設定値格納ファイルやレジストリ、インストールフォルダなどが重複しないように、留意して作成する必要があります。
とはいえ、新旧のメジャーバージョンを共存可能に作成したとしても、旧メジャーバージョンを削除したいというケースは良くある事だと思います。
Major Upgradeにおいて、上書きインストール(=旧メジャーバージョンの削除)を実施したい場合は、Orca を使って、下記のようにMSIファイルを編集することで実現できます。
1. プログラムのバージョン番号を更新
上書きインストール時に、同名ファイルが存在する場合、ファイルを上書きするかどうかは、バージョン番号で判定されます。(バージョン番号を持つファイルの場合)
例えば、Visual Basic 6.0 (VB6) で開発したソフトであれば、該当プロジェクトを開き、プロジェクトのプロパティ内のバージョン番号を変更しましょう。
VB6のバージョン番号は、a.b.cの3桁で指定するようになっており、
aメジャー番号
bマイナー番号
cリビジョン番号
となります。

ここで、コンパイルされた実行ファイルの「プロパティ−バージョン情報」を見ると、実際のバージョン番号は4桁で管理されていることがわかります。
具体的には、a.b.0.cとなっており、3桁目として0が既定されているようです。
本来、この3桁目は、ビルド番号となるはずですが、VB6にはビルドという概念がないため、省略されているものと思います。
例えば、VB6のバージョン指定を1.0.1とした場合、実際のバージョン番号は"1.0.0.1"となります。また、実行ファイルの「プロパティ−バージョン情報−詳細」の中では、別表記として、"1.00.0001"のように表されています。

2. 製品コード(ProductCode)を更新
VSIで、バージョンアップしたいソフト用のVSIプロジェクトファイル("*.WJP")ファイルを開きます。

メニューのプロジェクト(P)−***のプロパティ(S)から、プロパティフォームを開き、製品情報タグの中の「製品コード」を変更します。(横にある「新規コード」ボタンをクリックします。)


なお、更新用コード(UpgradeCode)というものもありますが、これは商品ファミリーコードのようなものなので、変更する必要はありません。
もし間違って変更してしまうと、別の製品として認識されるようになってしまうので気を付けましょう。
もしもの場合に備えて、「更新用コード」メモしておくと良いかもしれません。
誤って更新してしまった場合でも、手入力で訂正できます。

また、VSI上からは確認できませんが、MSIファイルには、PackageCodeというものも存在します。
VSIでは、PackageCodeは、ProductCode(製品コード)と同じ値になります。
3. 製品バージョン(ProductVersion)を更新
製品情報タグの中の「バージョン」を変更します。
VSIのバージョン番号は、a.b.c.dの4桁で管理されており、
aメジャー番号
bマイナー番号
cビルド番号
dリビジョン番号
となっています。

4桁目はバージョンアップされているかどうか(既存ファイルを上書きするかどうか)のチェック対象とはならないので、最初の3桁のいずれか(またはその組み合わせ)を変更するようにします。
4. MSIファイルを生成
適用ボタンで変更内容を更新した後、ビルドしてMSIファイルを再作成し、VSIを終了します。
5. MSIファイルをOrcaで開く
作成したMSIファイルの上で右クリックして、「Edit with Orca」を実行し、Orca を起動します。

「Edit with Orca」は Orca をインストールすることで作成されます。
6. カスタムアクションを作成
テーブル「CustomAction」を開き、コマンド「ADD ROW」で、下記のレコードを追加します。
ActionTypeSourceTarget
CA_NEWFOUND19(空白)これより新しいバージョンがインストールされています。
ここでは、インストール済みのバージョンよりも古いバージョンをインストールしようとした場合に、エラーメッセージを表示してインストールを中断する「動作」を追加します。
"Action=CA_NEWFOUND"は重複しない適当な名前で、"TYPE=19"は"Target"で指定されるメッセージの表示とインストールの中断を表す定数です。
7. 処理フローを追加 1/2
テーブル「InstallExecuteSequence」を開き、コマンド「ADD ROW」で、下記のレコードを追加します。
ActionConditionSequence
RemoveExistingProductsOLD_FOUND6700
InstallExecuteSequenceは、インストール作業の流れを設定するテーブルです。
ここでは、旧バージョンが見つかった場合に、それを削除する処理を追加します。
"Action=RemoveExistingProducts"は、旧バージョンが見つかった場合にそれを削除することを示し、"Sequence"の数字は、実行される順番を表します。
"Sequence"は、既存の"Action=InstallInitialize(通常1500)"〜"Action=InstallFinalize(通常6600)"の範囲以外で、かつ他のレコードと重複しない数字であれば何でも良いです。
ただし、インストール作業がキャンセルされることもあり得ますし、また、メジャーアップグレードは、新旧の共存が可能(新版のインストール後に旧版をアンインストールしても問題ない)という前提が肯定されるなら、新版のインストールが完了(Action=InstallFinalize)した後に実行すれば良いでしょう。
8. 処理フローを追加 2/2
テーブル「InstallUISequence」およびテーブル「InstallExecuteSequence」をそれぞれ開き、コマンド「ADD ROW」で、下記のレコードを追加します。
ActionConditionSequence
FindRelatedProducts(空白)2
CA_NEWFOUNDNEW_FOUND3
InstallUISequenceは、インストール作業を行うための準備の流れを設定するテーブルです。
このテーブルは、ユーザーがサイレントインストールを行った場合などに、処理されないこともありうるので、念のため、テーブル「InstallExecuteSequence」にも同様の処理を記述しておきます。
ここでは、バージョンチェック処理と、中断処理を追加します。
"Action=FindRelatedProducts"によって、インストール時(修復、アンインストールを除く)に、後述12のUpgradeテーブル内のUpgradeCodeがチェックされ、ActionPropertyに値(=製品コード)が代入されます。
なお、"FindRelatedProducts"は、その製品コードで初めてインストールされるときにだけ動作します。つまり、製品コードが変更されるケース、すなわちメジャーアップグレードのときにだけ動作し、製品コードが変更されないケース、すなわちマイナーアップグレードやスモールアップグレードのときは動作しません。
"Action=CA_NEWFOUND"は、"FindRelatedProducts"の処理により、カスタム条件"NEW_FOUND"(後述11)に値が代入されている時、前述8で指定したカスタムアクションCA_NEWFOUNDを実行することを意味します。 "Sequence"の数字は、実行される順番を表します。他のレコードと重複しない数字であれば何でも良いですが、中断処理が発動される場合に備えて、なるべく早い段階で処理を行うようにした方が良いでしょう。
9. プロパティを追加
テーブル「Property」を開き、コマンド「ADD ROW」で、下記のレコードを追加します。
PropertyValue
SecureCustomPropertiesNEW_FOUND;OLD_FOUND
ここでは、SecureCustomPropertiesプロパティとして、
 NEW_FOUND

 OLD_FOUND
の2つの値を追加します。
10. テーブル「Upgrade」を追加
コマンド「ADD Table」でテーブル「Upgrade」を作成し、その後、コマンド「ADD ROW」で、下記のレコードを追加します。
UpgradeCodeVersionMinVersionMaxLanguageAttributesRemoveActionProperty
upgrade code(空白)xx.xx.xxxx(空白)256(空白)OLD_FOUND
upgrade codexx.xx.xxxx(空白)(空白)2(空白)NEW_FOUND
UpgradeCode は、前述11のPropertyテーブルで確認することができます。
ここを編集する前に、あらかじめ前述11の時点でコピー(CTRL+C)をしておいて貼り付けると良いでしょう。
"xx.xx.xxxx"は、前述3で更新したバージョン番号(メジャー/マイナー/ビルド番号)です。(リビジョン番号を記述しても構いませんが、無視されます。)
"Attributes"には定数を指定します。"2"は「検索するが削除はしない」を意味し、"256"は「VersionMinを含む」(="VersionMinより大きい"ではなく"VersiuonMin以上"とする)事を意味します。
ちなみに、"VersionMax"を指定した場合で、"VersionMaxを含む"とする場合は、定数"512"を加えます。
"VersionMin"および"VersionMax"は、どちらか一方を必ず指定しなければなりません。
11. MSIファイルを保存
変更内容を保存して完了です。

補足
WinNT系のOSにおいて、旧バージョンと新バージョンでインストールターゲット(ログインユーザーor全てのユーザー)が異なる場合、たとえ管理者権限を持っていたとしても、FindRelatedProductsによる新旧バージョンの検索が失敗します。
(インストールターゲットの変更については別ページ NT系のOSでインストールターゲットを「全てのユーザー」にする方法 を参照)
このため、上記方法では、上書きインストールを確実に行うことができません。
これを解決するには、上記7.〜10.までを下記のものに差し替える方法もあります。
1. テーブル「CustomAction」を開き、コマンド「ADD ROW」で、下記のレコードを追加します。
ActionTypeSourceTarget
CA_PRODUCTREMOVE2146SystemFoldermsiexec.exe /x {ProductCode} /qn
ここでは、インストール済みの旧バージョンを削除する「動作」を追加します。
"Action=CA_PRODUCTREMOVE"は重複しない適当な名前で、"TYPE=98"は"Source"で指定されるフォルダを作業フォルダにして、"Target"で指定されるファイルを実行することを表す定数(=34)と、同期実行およびエラーが発生してもそれを無視してインストールを継続することを表す定数(=64)の合計値に、アクションを管理者権限で実行することを示す定数(=2048)を加えた値です。
削除したいProductCodeが複数ある場合、すなわち、これまでにメジャーバージョンを複数回行っている場合は、その数に応じて、カスタムアクションを作成して下さい。
2. テーブル「ControlEvent」を開き、コマンド「ADD ROW」で、下記のレコードを追加します。
DialodControlEventArgumentConditionOrder
ConfirmFormNextDoActionCA_PRODUCTREMOVEREMOVE="" AND REINSTALL=""2
AdminConfirmFormNextDoActionCA_PRODUCTREMOVEREMOVE="" AND REINSTALL=""2
テーブル「ControlEvent」には、すでに"Dialod=ConfirmForm"および"Control=Next"となっているレコードが複数あると思います。
"Order"は、ボタン「Next」を押した時に実行する順番となりますので、既存のものと重複しない番号として下さい。 また、"Condition"として、アンインストール時および修復時には実行しないようにしました。
インストールターゲット(全ユーザ−orログインユーザー)に関わらず、全ての旧バージョンを削除することができます。(ただし、管理者権限が必要)
"ConfirmForm"、"AdminConfirmForm"および"Next"は、インストールダイアログおよびダイアログ上に配置されるコントロールの名称です。パッケージファイルを作成したツールによって、この名称が異なるかもしれませんので、適宜変更して下さい。

参考URL
Patching and Upgrades
Preventing an Old Package from Installing Over a Newer Version
Preparing an Application for Future Major Upgrades
PRB: Multiple Entries in the Add/Remove Programs Utility After a Windows Installer Update
Specifying a Per-User or Per-Machine Installation



インストーラ講座の目次へページ最上部へ