┏第60号━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃         .NETプログラミング研究         ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ──<メニュー>─────────────────────── ■.NET Tips ・デプロイメントプロジェクトによるアップデート ・インストーラでファイルを上書きする ─────────────────────────────── ─────────────────────────────── ■.NET Tips ─────────────────────────────── ●デプロイメントプロジェクトによるアップデート ここでは、VS.NETのデプロイメントプロジェクトで作成するMSIファ イルで、アプリケーションのアップデートインストールができるよう にする方法を説明します。 まずは、Windows Installerで定義されている3つのアップデートのタ イプから説明します。 ★アップデートの3つのタイプ Windows Installerでは、アップデートのタイプを、Small Update、 Minor Upgrade、Major Upgradeの3つに分類しています。それぞれの タイプに関して詳しくは、「Platform SDK: Windows Installer」で 説明されています。 [URL]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┃ ┣━━━━━━━╋━━━━━━╋━━━━━━━━╋━━━━━━┫ ┃Small Update ┃変更する ┃変更しない ┃変更しない ┃ ┣━━━━━━━╋━━━━━━╋━━━━━━━━╋━━━━━━┫ ┃Minor Upgrade ┃変更する ┃変更する ┃変更しない ┃ ┣━━━━━━━╋━━━━━━╋━━━━━━━━╋━━━━━━┫ ┃Major Upgrade ┃変更する ┃変更する ┃変更する ┃ ┗━━━━━━━┻━━━━━━┻━━━━━━━━┻━━━━━━┛ Package Codeは、MSIファイルをアップデートする時に必ず変更する 必要があります。VS.NETではMSIファイルを作成するたびにPackage Codeを変更しますので、通常は気にする必要はありません。 [URL]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プロパティで指定します。 [URL]ProductVersion Property http://msdn.microsoft.com/library/en-us/msi/setup/productversion.asp [URL]Version プロパティ http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfVersionProperty.asp Product Codeは、Major Upgradeでのみ変更します。VS.NETでは、 ProductCodeプロパティで指定します。 [URL]ProductCode Property http://msdn.microsoft.com/library/en-us/msi/setup/productcode.asp [URL]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で新しいバージョンがインストールされている ときに古いバージョンをインストールできないようにする方法や、古 いバージョンをアンインストールしてから新しいバージョンをインス トールする方法に関しては、後述します。 ★どのアップデートを選択するか どのような状況でどのタイプのアップデートを行うべきかについては、 「Patching and Upgrades」等で説明されています。簡単に説明する と、次のようになります。 まず、別の製品として扱えるアップデートを行うには、Major Upgradeとします。また、アップデート前のバージョンと、アップデー ト後のバージョンを区別する必要があるならばMinor Upgrade、そう でなければSmall Updateとします。一般的に言われるquick fix engineering(QFE)がSmall Updateに、service pack(SP)がMinor Upgradeに相当するということです。 これ以外にも、いくつかのガイドラインがあります。これに関しては、 以下のリンク先で説明されています。 [URL]Changing the Product Code http://msdn.microsoft.com/library/en-us/msi/setup/changing_the_product_code.asp [URL]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以上が必須のため。) ★アップデートの実際 いよいよアップデートの具体的な方法についての説明に入ります。VS. NETではMSIファイルしか作れず、パッチは作れませんので、MSIファ イルによるアップデートの方法を考えなければなりません。 MSIファイルによるアップデートに関しては、次のページが参考にな ります。 [URL]Applying Small Updates by Reinstalling the Product http://msdn.microsoft.com/library/en-us/msi/setup/applying_small_updates_by_reinstalling_the_product.asp [URL]Applying Major Upgrades by Installing the Product http://msdn.microsoft.com/library/en-us/msi/setup/applying_major_upgrades_by_installing_the_product.asp [URL]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の時に古いバージョンをインストールしようとすると、イ ンストールの実行前に「このプロダクトの新しいバージョンが既にイ ンストールされているためインストールできません。」というメッセー ジが表示され、インストールが未完了のまま終了します。 [URL]DetectNewerInstalledVersion プロパティ http://www.microsoft.com/japan/msdn/library/ja/vsintro7/html/vxgrfDetectNewerInstalledVersionProperty.asp またRemovePreviousVersionsプロパティをTrueにすると、既に古いバー ジョンがインストールされていたらこれをアンインストールしてから 新しいパッケージをインストールするようになります。 前に述べたとおり、Major Upgradeでは別の製品として扱われるため、 古いバージョンが既にインストールされていてもそれとは別の製品と してインストールされます。つまりMajor Upgradeは前のバージョン を上書きして(あるいは置き換えて)インストールするということで はありません。前のバージョンと同じフォルダにインストールすれば、 ファイルを上書きすることはできますが、コントロールパネルの「プ ログラムの追加と削除」には古いバージョンが残されたまま、新しい バージョンの項目が追加されます。つまり、新しいバージョンを古い バージョンに置き換える場合は、古いバージョンをアンインストール してから新しいバージョンをインストールしなければなりません。そ れを自動的に行うようにするのが、RemovePreviousVersionsプロパテ ィです。 [URL]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」としているためです)。また、前の バージョンのインストールが「このユーザーのみ」で、新しいバージ ョンを「すべてのユーザー」としてインストールする時もそうです。 これらに関して、以下のページで幾つか紹介されています。 [URL]Why Doesn't My Major Upgrade Work? http://www.installsite.org/pages/en/msifaq/a/1038.htm [URL]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先をご覧ください。 [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」をご覧ください。 [URL]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で行います。 [URL]REINSTALL Property http://msdn.microsoft.com/library/en-us/msi/setup/reinstall.asp [URL]REINSTALLMODE Property http://msdn.microsoft.com/library/en-us/msi/setup/reinstallmode.asp これでこのパッケージが再インストールされるわけですが、問題はは じめてのインストールの時には何もインストールされないということ です。よって、初めてのインストールであるか判断して、プロパティ を適当に変更しなければなりません。 この対処法もInstallSiteで説明されていますが、これにはOrcaが必 要です。 まずCustomActionテーブルに次のような行を追加します。 ┏━━━━━━━┳━━┳━━━━━┳━━━┓ ┃Action ┃Type┃Source ┃Target┃ ┣━━━━━━━╋━━╋━━━━━╋━━━┫ ┃fix_reinstall ┃51 ┃REINSTALL ┃{} ┃ ┗━━━━━━━┻━━┻━━━━━┻━━━┛ また、InstallExecuteSequenceとInstallUISequenceテーブルに次の ような行を追加します。(Sequence列はCostFinalizeの前になるよう に調節してください。) ┏━━━━━━━┳━━━━━━━┳━━━━┓ ┃Action ┃Condition ┃Sequence┃ ┣━━━━━━━╋━━━━━━━╋━━━━┫ ┃fix_reinstall ┃NOT Installed ┃999 ┃ ┗━━━━━━━┻━━━━━━━┻━━━━┛ 以上のようにすることにより、既に同じProductCodeの製品がインス トールされている時は、REINSTALLプロパティが削除されるようにな ります。これで、初めてインストールする時も正常にインストールさ れるようになります。 補足:上記のようにMSIファイルのデータベースをいじる方法以外に、 Bootstrapperを使って既に同じProductCodeの製品がインストールさ れているかを調べ、コマンドラインを変更する方法もあります。これ を可能にするBootstrapperとしては、「VSSetup」があります。 [URL]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プロパティによる 方法のほうが優れていますので、この方法を使う必要はないでしょう。 この方法の説明は省略させていただきます。 ─────────────────────────────── ●インストーラでファイルを上書きする 先に説明したように、VS.NETのデプロイメントプロジェクトでアップ デートする時は、通常RemovePreviousVersionsプロパティを使って前 のバージョンを削除してからインストールするという方法が用いられ るため、インストーラによるファイルの上書きに気を使うケースはあ まりないでしょう。しかし、Permanentプロパティでアンインストー ルで削除できないようにしたり、先に紹介した再インストールをする 場合などには、既に同名のファイルが存在する時に、インストーラが どのような判断でそのファイルを上書きするかしないかを決定してい るのか知っておく必要があります。 Windows Installerがどのようなルールでこれを決定しているかにつ いては、「File Versioning Rules」等で説明されています。 [URL]File Versioning Rules http://msdn.microsoft.com/library/en-us/msi/setup/file_versioning_rules.asp [URL]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プロパティを変更する方法は、先に説 明しました。 [URL]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を設定することにより、ファイルを 上書きする方法が紹介されています。 [URL]Frequently Asked Questions About Windows Installer http://www.microsoft.com/windows2000/community/centers/management/msi_faq.mspx =============================== ■ここで示したコードの多くはまずC#で書き、それを「C# to VB.NET Translator」でVB.NETのコードに変換し、修正を加えたものです。 [URL]C# to VB.NET Translator http://authors.aspalliance.com/aldotnet/examples/translate.aspx ■このマガジンの購読、購読中止、バックナンバー、説明に関しては  次のページをご覧ください。  http://www.mag2.com/m/0000104516.htm ■発行人・編集人:どぼん!  (Microsoft MVP for Visual Basic, Oct 2005-Oct 2006)  http://dobon.net  dobon_info@yahoo.co.jp ■ご質問等はメールではなく、掲示板へお願いいたします。  http://dobon.net/vb/bbs.html ■上記メールアドレスへのメールは確実に読まれる保障はありません  (スパム、ウィルス対策です)。メールは下記URLのフォームメール  から送信してください。  http://dobon.net/mail.html Copyright (c) 2003 - 2005 DOBON! All rights reserved. ===============================