• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(.NETプログラミング研究 第60号)

#navi(.NETプログラミング研究)

#contents

*.NETプログラミング研究 第60号 [#k5a1a1bf]

**.NET Tips [#hae8061f]

**デプロイメントプロジェクトによるアップデート [#z60c1034]

#column(注意){{
この記事の最新版は「[[セットアッププロジェクトによるアップデート>http://dobon.net/vb/dotnet/deployment/upgrades.html]]」で公開しています。
この記事の最新版は「[[セットアッププロジェクトによるアップデート>https://dobon.net/vb/dotnet/deployment/upgrades.html]]」で公開しています。
}}

ここでは、VS.NETのデプロイメントプロジェクトで作成するMSIファイルで、アプリケーションのアップデートインストールができるようにする方法を説明します。

まずは、Windows Installerで定義されている3つのアップデートのタイプから説明します。

***アップデートの3つのタイプ [#md412cd5]

Windows Installerでは、アップデートのタイプを、Small Update、Minor Upgrade、Major Upgradeの3つに分類しています。それぞれのタイプに関して詳しくは、「Platform SDK: Windows Installer」で説明されています。

-[[Patching and Upgrades>http://msdn.microsoft.com/library/en-us/msi/setup/patching_and_upgrades.asp]]

これらのタイプの違いは、Package Code、Product Version、Product Codeを変えるか変えないかという点にあります。以下にその違いを表で示します。

|タイプ|Package Code|Product Version|Product Code|h
|Small Update|変更する|変更しない|変更しない|
|Minor Upgrade|変更する|変更する|変更しない|
|Major Upgrade|変更する|変更する|変更する|

Package Codeは、MSIファイルをアップデートする時に必ず変更する必要があります。VS.NETではMSIファイルを作成するたびにPackage Codeを変更しますので、通常は気にする必要はありません。

-[[Package Codes>http://msdn.microsoft.com/library/en-us/msi/setup/package_codes.asp]]

補足:Package Codeを確認、変更するには、エクスプローラでMSIファイルのプロパティを表示し、「概要」ページの「改定番号」を見るか、Orcaのメニューの「View」-「Summary Information」を使います。

Product Versionは、Minor UpgradeとMajor Upgradeで変更します。Product VersionはVS.NETでは、Versionプロパティで指定します。

-[[ProductVersion Property>http://msdn.microsoft.com/library/en-us/msi/setup/productversion.asp]]
-[[Version プロパティ>http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfVersionProperty.asp]]

Product Codeは、Major Upgradeでのみ変更します。VS.NETでは、ProductCodeプロパティで指定します。

-[[ProductCode Property>http://msdn.microsoft.com/library/en-us/msi/setup/productcode.asp]]
-[[ProductCode プロパティ>http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfProductCodeProperty.asp]]

Product Codeを変更すると、前のバージョンのパッケージとは別の製品として扱われるため、前のバージョンが既にインストールされていたとしても、インストールすることができます。これに対してProduct Codeを変更しなかった時は同じ製品として扱われるため、前のバージョンがインストールされていると、「別のバージョンの製品がすでにインストールされています」メッセージが表示され(注)、前のバージョンをアンインストールしないと新しいバージョンをインストールすることができません。

注:Package Code、Product Version、Product Codeのすべてを変更しなかった時は、「アプリケーションの修正または削除」ダイアログが表示されます。

補足:Major Upgradeで新しいバージョンがインストールされているときに古いバージョンをインストールできないようにする方法や、古いバージョンをアンインストールしてから新しいバージョンをインストールする方法に関しては、後述します。

***どのアップデートを選択するか [#e3459470]

どのような状況でどのタイプのアップデートを行うべきかについては、「Patching and Upgrades」等で説明されています。簡単に説明すると、次のようになります。

まず、別の製品として扱えるアップデートを行うには、Major Upgradeとします。また、アップデート前のバージョンと、アップデート後のバージョンを区別する必要があるならばMinor Upgrade、そうでなければSmall Updateとします。一般的に言われるquick fix engineering(QFE)がSmall Updateに、service pack(SP)がMinor Upgradeに相当するということです。

これ以外にも、いくつかのガイドラインがあります。これに関しては、以下のリンク先で説明されています。

-[[Changing the Product Code>http://msdn.microsoft.com/library/en-us/msi/setup/changing_the_product_code.asp]]
-[[InstallSite: Windows Installer Updates and Patches>http://www.installsite.org/pages/en/msi/updates.htm]]

この内、VS.NETを使用してMSIファイルを作成する際に問題となりそうな箇所を以下に列挙します。(英語の解読に自信がないため、正確でない点があるかもしれません。)

-Small Update、Minor Upgradeでは、MSIファイルの名前を変えてはいけない。ファイル名を変えるならば、Major Upgradeとする。
-バージョンのあるファイルが修正された場合、バージョンは増加していなければならない。(VS.NETでは、ファイルのバージョンをFileテーブルに書き込んでいるようなので。)
-Small UpdateはWindows Installerパッチパッケージとして出荷する。
-同一システムでアップデート前のアプリケーションと共存できるようにするには、Major Upgradeとする。
-ファイルやレジストリキーが削除されるならば、Major Upgradeとする。(VS.NETでは、ファイルやレジストリキーをそれぞれ一つのcomponentとして扱っているため。)
-新しいファイルやレジストリキーを追加しても、Major Upgradeとしなければならない訳ではない。(.NET Frameworkでは、Windows Installer 2.0以上が必須のため。)

***アップデートの実際 [#r184b8d9]

いよいよアップデートの具体的な方法についての説明に入ります。VS.NETではMSIファイルしか作れず、パッチは作れませんので、MSIファイルによるアップデートの方法を考えなければなりません。

MSIファイルによるアップデートに関しては、次のページが参考になります。

-[[Applying Small Updates by Reinstalling the Product>http://msdn.microsoft.com/library/en-us/msi/setup/applying_small_updates_by_reinstalling_the_product.asp]]
-[[Applying Major Upgrades by Installing the Product>http://msdn.microsoft.com/library/en-us/msi/setup/applying_major_upgrades_by_installing_the_product.asp]]
-[[InstallSite: Minor and Major Upgrades Using IPWI>http://www.installsite.org/files/iswi/Upgrading.html]]

補足:「InstallSite: Minor and Major Upgrades Using IPWI」では3つの方法が紹介されていますが、この内1と3がそれぞれ「Applying Small Updates by Reinstalling the Product」と「Applying Major Upgrades by Installing the Product」に相当します。

「InstallSite: Minor and Major Upgrades Using IPWI」では3つの方法が紹介されていますが、この内VS.NETで扱えるのは最後の「3: Major upgrades」だけです。まずはこの方法から紹介します。

''Major Upgrade''

この方法は、Major Upgradeを行うものです。よって、Product VersionとProduct Codeの両方を変更しなければなりません。VS.NETでProduct Versionを変更するには、デプロイメントプロジェクトのVersionプロパティを変更します(注)。

注:Product Versionは「.」で区切られた数字のうち、はじめの3つのみを考慮し、残りは無視しますので、少なくともはじめの3つの数字のいずれかを変更する必要があります。

VS.NETではVersionプロパティを変更すると、ProductCodeとPackageCodeの変更を勧められます。ここではMajor Upgradeを行うため、「はい」を選択し、Product Codeも変更します。(後でProductCodeプロパティを変更することもできます。)

VS.NETでは、Major Upgradeを行う際の動作を、DetectNewerInstalledVersionプロパティとRemovePreviousVersionsプロパティで指定することができます。

DetectNewerInstalledVersionプロパティをTrueにすると、現在インストールされているバージョンよりも古いバージョンをインストールすることができなくなります。DetectNewerInstalledVersionプロパティがTrueの時に古いバージョンをインストールしようとすると、インストールの実行前に「このプロダクトの新しいバージョンが既にインストールされているためインストールできません。」というメッセージが表示され、インストールが未完了のまま終了します。

-[[DetectNewerInstalledVersion プロパティ>http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfDetectNewerInstalledVersionProperty.asp]]

またRemovePreviousVersionsプロパティをTrueにすると、既に古いバージョンがインストールされていたらこれをアンインストールしてから新しいパッケージをインストールするようになります。

前に述べたとおり、Major Upgradeでは別の製品として扱われるため、古いバージョンが既にインストールされていてもそれとは別の製品としてインストールされます。つまりMajor Upgradeは前のバージョンを上書きして(あるいは置き換えて)インストールするということではありません。前のバージョンと同じフォルダにインストールすれば、ファイルを上書きすることはできますが、コントロールパネルの「プログラムの追加と削除」には古いバージョンが残されたまま、新しいバージョンの項目が追加されます。つまり、新しいバージョンを古いバージョンに置き換える場合は、古いバージョンをアンインストールしてから新しいバージョンをインストールしなければなりません。それを自動的に行うようにするのが、RemovePreviousVersionsプロパティです。

-[[RemovePreviousVersions プロパティ>http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfRemovePreviousVersionsProperty.asp]]

なおこのようなMajor UpgradeではUpgradeCodeが使われるため、UpgradeCodeは絶対に変えてはいけません。

このようにVS.NETでアップデートを行うMSIファイルを作成する時はMajor Upgradeとし、DetectNewerInstalledVersionとRemovePreviousVersionsプロパティをTrueにするというやり方が基本となるでしょう。

注意:RemovePreviousVersionsプロパティをTrueにしても前のバージョンがアンインストールされないケースが幾つかあります。例えば、Versionプロパティが1.0.0以下の製品が既にインストールされていたとしてもアンインストールしません(これはVS.NETがUpgradeテーブルのVersionMin列を「1.0.0.0」としているためです)。また、前のバージョンのインストールが「このユーザーのみ」で、新しいバージョンを「すべてのユーザー」としてインストールする時もそうです。これらに関して、以下のページで幾つか紹介されています。

-[[Why Doesn't My Major Upgrade Work?>http://www.installsite.org/pages/en/msifaq/a/1038.htm]]
-[[Simple Talk ≫ Blog Archive ≫ Updates to setup projects>http://www.simple-talk.com/2005/07/18/updates-to-setup-projects/]]

注意:RemovePreviousVersionsプロパティをTrueとして、Installerクラスを使ったカスタムアクションをインストール時とアンインストール時に使用している場合、新しいバージョンのインストールで古いバージョンのInstallメソッドが呼び出されるというバグがあります。詳しくは、以下のURL先をご覧ください。

-[[BUG: Visual Studio .NET Setup Projects Execute Custom Action of Previous Version when Upgrading>http://support.microsoft.com/kb/555184/en-us]]

補足:DetectNewerInstalledVersionとRemovePreviousVersionsプロパティはUpgradeテーブルを使用するための設定です。DetectNewerInstalledVersionのAttributesはmsidbUpgradeAttributesVersionMinInclusive+msidbUpgradeAttributesOnlyDetect、RemovePreviousVersionsのAttributesはmsidbUpgradeAttributesVersionMinInclusiveとなります。詳しくは、「Platform SDK」をご覧ください。

-[[Upgrade Table>http://msdn.microsoft.com/library/en-us/msi/setup/upgrade_table.asp]]

''再インストール''

「InstallSite: Minor and Major Upgrades Using IPWI」の「1: Upgrading by reinstalling」では、再インストールによる方法が紹介されています。この方法はProduct Codeを変更しないアップグレードでのみ可能です。残念ながらVS.NETだけではできません(最後の「補足」で紹介するようなツールを使えば、可能です)。

この方法では、MSIファイルの再インストールを

msiexec /i Setup1.msi REINSTALLMODE=voums REINSTALL=ALL

のようなコマンドラインで実行します。なお、既にあるファイルを置き換えるか、レジストリキーを書き換えるかの指定は、REINSTALLMODEで行います。

-[[REINSTALL Property>http://msdn.microsoft.com/library/en-us/msi/setup/reinstall.asp]]
-[[REINSTALLMODE Property>http://msdn.microsoft.com/library/en-us/msi/setup/reinstallmode.asp]]

これでこのパッケージが再インストールされるわけですが、問題ははじめてのインストールの時には何もインストールされないということです。よって、初めてのインストールであるか判断して、プロパティを適当に変更しなければなりません。

この対処法もInstallSiteで説明されていますが、これにはOrcaが必要です。

まずCustomActionテーブルに次のような行を追加します。

|Action|Type|Source|Target|h
|fix_reinstall|51|REINSTALL|{}|

また、InstallExecuteSequenceとInstallUISequenceテーブルに次のような行を追加します。(Sequence列はCostFinalizeの前になるように調節してください。)

|Action|Condition|Sequence|h
|fix_reinstall|NOT Installed|999|

以上のようにすることにより、既に同じProductCodeの製品がインストールされている時は、REINSTALLプロパティが削除されるようになります。これで、初めてインストールする時も正常にインストールされるようになります。

補足:上記のようにMSIファイルのデータベースをいじる方法以外に、Bootstrapperを使って既に同じProductCodeの製品がインストールされているかを調べ、コマンドラインを変更する方法もあります。これを可能にするBootstrapperとしては、「VSSetup」があります。

-[[VSSetup>http://www.vinga.se/products/shareware/vssetup/default.htm]]

''MsiExecでアンインストールする''

「InstallSite: Minor and Major Upgrades Using IPWI」の「2: Upgrading by launching MsiExec」では、MsiExecにより指定したProductCodeの製品をアンインストールしてから新たなパッケージをインストールする方法が紹介されています。これもVS.NETだけではできませんが、先に紹介したRemovePreviousVersionsプロパティによる方法のほうが優れていますので、この方法を使う必要はないでしょう。この方法の説明は省略させていただきます。

***インストーラでファイルを上書きする [#g1169d99]

先に説明したように、VS.NETのデプロイメントプロジェクトでアップデートする時は、通常RemovePreviousVersionsプロパティを使って前のバージョンを削除してからインストールするという方法が用いられるため、インストーラによるファイルの上書きに気を使うケースはあまりないでしょう。しかし、Permanentプロパティでアンインストールで削除できないようにしたり、先に紹介した再インストールをする場合などには、既に同名のファイルが存在する時に、インストーラがどのような判断でそのファイルを上書きするかしないかを決定しているのか知っておく必要があります。

Windows Installerがどのようなルールでこれを決定しているかについては、「File Versioning Rules」等で説明されています。

-[[File Versioning Rules>http://msdn.microsoft.com/library/en-us/msi/setup/file_versioning_rules.asp]]
-[[Replacing Existing Files>http://msdn.microsoft.com/library/en-us/msi/setup/replacing_existing_files.asp]]

このルールをごく簡単に説明すると、次のようになります(簡略化しているため、厳密には正確ではありません)。

まずバージョンのあるファイルの場合は、インストールするファイルのバージョンがより新しければ、上書きします。バージョンのないファイルの場合は、既にあるファイルが更新されていれば、上書きしません。ファイルが更新されたとみなされるのは、ファイルの作成日時が更新日時より古い場合です。

この動作は、REINSTALLMODEプロパティで変更することができます。デフォルトでREINSTALLMODEプロパティは「omus」ですが、この「o」が既にあるファイルのバージョンが古い場合に置き換えることを意味しています。もし同じバージョンでも上書きする場合は「o」の代わりに「e」とします。バージョンが違えば上書きするのであれば、「d」とします。さらに、バージョンやタイムスタンプに関係なく、上書きをしないのならば「p」を、逆に強制的に上書きするのであれば、「a」とします。なおREINSTALLMODEプロパティを変更する方法は、先に説明しました。

-[[REINSTALLMODE Property>http://msdn.microsoft.com/library/en-us/msi/setup/reinstallmode.asp]]

また、「Frequently Asked Questions About Windows Installer」の「How do I force-update an unversioned file during an upgrade, even if the user has modified it?」では、ユーザーが更新したバージョンのないファイルを強制上書きする方法が説明されています。ここでは、FileテーブルでVersionを設定することにより、ファイルを上書きする方法が紹介されています。

-[[Frequently Asked Questions About Windows Installer>http://www.microsoft.com/windows2000/community/centers/management/msi_faq.mspx]]

**コメント [#kb8426e1]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2005-10-06 (木) 18:00:00,DOBON!,2010-03-22 (月) 02:46:04,DOBON!)


[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]