Lesson 4 アップグレードとモジュラー化

1. 古いのを探す

何らかのアップデートやアップグレードをするときに最初にすることは、変更したい前のバージョンが有ることを確認することです。

Windows Installer はそれを確認するために Product タグの UpgradeCode 属性を頼りにします。 そのため、現在のプログラムを後でアップグレードする予定が無い場合であっても、常に製品に UpgradeCode を持たせておくことが非常に重要です。 将来のことは決して分りませんし、一旦外に出してしまってからでは、もう出荷し直すことは出来ません。

製品を同じアップグレード・バージョンでアップグレードしようとする限りは、同一の UpgradeCode GUID を保持してください。 通常の場合、このことは、Version 1.x の全てに一つのコード、Version 2.x にもう一つ別のコード、、、ということを意味します。

<?xml version='1.0' encoding='utf-8'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
  <Product Name='ほげ 1.0'
      Id='YOURGUID-86C7-4D14-AEC0-86416A69ABDE'
      UpgradeCode='YOURGUID-7349-453F-94F6-BCB5110BA4FD'
      Version='1.0.0' Manufacturer='ぴよソフト'
      Language='1041' Codepage='932'>
    <Package Id='*' Keywords='インストーラ'
        Description="ぴよソフト's ほげ 1.0 インストーラ"
        Comments='ほげはぴよソフトの登録商標です。'
        Manufacturer='ぴよソフト' InstallerVersion='100'
        Languages='1041' Compressed='yes' SummaryCodepage='932' />
      ...
    </Package>
  </Product>
</Wix>

今回の SampleUpgrade は、二つのインストーラ・パッケージから成り立っています。 両方とも、簡単な UI のインストーラ、SampleWixUI を元にしています。

訳註:SampleUpgrade の日本語版は Sample-4-1-Upgrade.zip です。

SampleUpgrade の第二のバージョンは、配置されたファイルの一つを新しいバージョンで置き換えるためのものです。 私たちはこれをマイナー・アップグレードだと考えて、Version を変えています。 外見上の変更が、人間が読むことが出来る NameDescription に対して加えられていることは言うまでもありません。

<Product Name='ほげ 1.0.1'
    Id='YOURGUID-86C7-4D14-AEC0-86416A69ABDE'
    UpgradeCode='YOURGUID-7349-453F-94F6-BCB5110BA4FD'
    Version='1.0.1' Manufacturer='ぴよソフト'
    Language='1041' Codepage='932'>
  <Package Id='*' Keywords='インストーラ'
      Description="ぴよソフト's ほげ 1.0.1 アップデータ" ... >

製品のどのバージョンをこのアップグレードによって置き換える予定なのか、ということについての記述も必要です。 Upgrade タグの Id 属性が、元のインストーラ・パッケージ(この例では古い方の SampleUpgrade)の UpgradeCode GUID を参照しています。 内部の UpgradeVersion タグは、更新対象となるバージョンの詳細を記述しています。 OnlyDetect は、インストーラに、前の製品を削除しないように指示しています (思い出してください。私たちはマイナー・アップグレードをやっています。 製品の古いバージョンを維持しながら、ファイルを一つだけ置き換えるのです。 もし、メジャー・アップグレードをやっているのだとしたら、そうする代りに、1.0.0 を削除して、1.1.0 をインストールするでしょう)。

MinimumMaximum が、このアップグレード・パッケージで更新することになるバージョンの範囲を示しています。 IncludeMaximumIncludeMinimum は、境界値が範囲に含まれるか否かを指定します (IncludeMaximum = yesMaximum で指定されたバージョン より低いか等しい バージョンを探すことを意味し、 IncludeMaximum = noMaximum より低い ものだけを探すことを意味します)。 これらの属性には既定値がありますが、ここでは、既定値には頼らず、常に明示的に記述することにします – 明解さと自己完結的な説明性のためには、省略せずに書く方が良いでしょう。

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

訳註:実際にここで探そうとしているのは、更新する対象のバージョンではありません。 そうではなくて、更新する必要のないバージョン、すなわち自分自身(SELFFOUND)、および、 更新してはいけないバージョン、すなわち自分よりも新しいバージョン(NEWERFOUND)を探そうとしています。

ソース・ファイルの中で Upgrade タグを使うと、新しい標準的なアクション、FindRelatedProducts が導入されます。 このアクションは、もし有れば、AppSearch の直前に走るようにスケジュールされます。 必要な場合には、InstallExecuteSequence タグの中で、スケジュールを変更することも出来ます。

FindRelatedProductsUpgrade タグの中を全部見て、リスト・アップされている全てのバージョンを探します。 該当するバージョンが存在した場合は、UpgradeVersion タグで指定されているプロパティ (この例では SELFFOUND または NEWERFOUND)に、そのバージョンの Product GUID が追記されます。 言うまでもなく、Windows Installer が探すことが出来るのは、指定された UpgradeCode を持っている .msi パッケージでインストールされた製品だけです — UpgradeCode を常に指定することが重要だという意味がこれで分ったでしょう。

もし、地域化されたソフトウェア・パッケージを開発しているのであれば、UpgradeVersionProduct タグの両方で Language 属性を指定することが可能です。 言語を指定するためには、いつものように Windows の言語識別子の数値を使って下さい。 言語を指定すると、FindRelatedProducts は、該当する言語の製品だけを探します。

私たちは、チェックが走った後で、関連するプロパティの存在および値に基づいて、適切な行動を取ることが出来ます。

  <CustomAction Id='AlreadyUpdated'
      Error='[ProductName] は既に 1.0.1 に更新されています。' />
  <CustomAction Id='NoDowngrade'
      Error='[ProductName] の新しいバージョンが既にインストールされています。' />

  <InstallExecuteSequence>
    <Custom Action='AlreadyUpdated'
        After='FindRelatedProducts'>SELFFOUND</Custom>
    <Custom Action='NoDowngrade' 
        After='FindRelatedProducts'>NEWERFOUND</Custom>
  </InstallExecuteSequence>

どういう理由かは知りませんが、スモール・アップデートとマイナー・アップグレードは、 .msi ファイルをダブル・クリックするだけでは走らせることが出来ません。 “この製品の別のバージョンが既にインストールされています” というエラーが出るのです。

知っとるわぃ、ボケ … とにかく、コマンド・ラインから起動しなくてはならないのです。

msiexec /i SampleUpgrade.msi REINSTALL=ALL REINSTALLMODE=vomus

どうやってこんな事を平均的なユーザーにやって貰おうか、などと尋ねるのはやめて下さいね。 Autorun.inf ファイルから起動したり、起動用の Setup.exe ラッパー・シェルをひねり出したりする方が良いですよ。

ご覧のように、このアップグレード・バージョンは双方向に正しく動作します。 これは自分より古いパッケージを置き換えますが、それだけでなく、将来、 プログラムがもっと先まで(例えば 1.0.2 以降に)更新されていた場合でも、対処出来ます。 より新しいバージョンを 1.0.1 にダウングレードして戻すようなことはしません。 絶対確実に間違いが無いようにするためには、このことは前もって計画しておかなくてはいけません。 一番初めに出荷するインストーラであっても、このセーフティー・ロックが組み込まれていなくてはなりません (その事を現在のサンプルの古い方のバージョンで確認して下さい)。

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

  <CustomAction Id='NoDowngrade'
      Error='[ProductName] の新しいバージョンが既にインストールされています。' />

  <InstallExecuteSequence>
    <Custom Action='NoDowngrade'
        After='FindRelatedProducts'>NEWERFOUND</Custom>
  </InstallExecuteSequence>

訳註:この章で説明されている「セーフティー・ロック」機構は、実際には、 プロダクト・コードが異なるパッケージ同士の間 (すなわち、メジャー・アップグレード) でなければ、期待している通りの動作はしません。

スモール・アップデートおよびマイナー・アップグレードの場合、すなわち、プロダクト・コードが同じパッケージ同士の間では、 "msiexec /i SampleUpgrade.msi REINSTALL=ALL REINSTALLMODE=vomus" によってパッケージを起動する必要があることは、本文で述べられている通りです。 この場合、Windows Installer は メンテナンス・モード で走ることになります。 ところが、メンテナンス・モードにおいては、FindRelatedProducts は何もせずに帰ってきてしまいます。 つまり、SELFFOUND も NEWERFOUND も設定されず、結果として、’AlreadyUpdated’ も ‘NoDowngrade’ も、実行されることは決してありません。 具体的に言うと、1.0.1 をインストールした後に 1.0.0 のインストーラを上記のコマンド・ラインで起動すると、 何の警告も表示せずに、最後まで走ってしまうのです。

"REINSTALLMODE=vomus" の場合、Windows Installer がファイルのバージョン番号(ファイルにバージョン番号がある場合) や更新日付を見て、ファイル単位でダウングレードを防止しますので、致命的な実害は生じません。 しかし、実際の動作と、ユーザーに対するフィードバックとの間に無視できないズレが生じますので、気持ちが悪いことは否定できません。

なお、プロダクト・コードが異なるパッケージ同士の間、すなわち、メジャー・アップグレード では、 この「セーフティー・ロック」機構が有効に働きます。

↑ 先頭  |  • 目次  |  « 前へ  |  次へ »  |  ∗ 原文

Table of Contents

1 始めよう

  1. ソフトウェア・パッケージ
  2. 中に入るファイル
  3. 使用に供する
  4. 便利な追加機能
  5. どこにインストールするか
  6. 条件付きインストール
  7. ファイルだけでなく
  8. 削除時の孤児化

2 ユーザー・インタフェイス

  1. 最初のステップ
  2. カスタムの設定
  3. UI の魔法
  4. 英語はわかりますか
  5. チェーンの新しい環
  6. 地域化を考える

3 イベントとアクション

  1. 列に並んで
  2. 追加のアクション
  3. 本に書かれていないこと
  4. コントロールをコントロールせよ
  5. マネージする方法
  6. 後の段階で

4 アップグレードとモジュラー化

  1. 古いのを探す
  2. 自分自身を置き換える
  3. パッチワーク
  4. 断片
  5. 融合するもの

5 Net と .NET

  1. .NET の枠組み
  2. ブートストラップ
  3. インターネットを起動する
  4. ウェブ・ディレクトリ
  5. サービスの提供

6 COM、式の構文、その他

  1. 違う色のコンポーネント
  2. 式の構文
  3. 書式指定文字列
  4. DDE 接続
  5. ディレクトリの作成
  6. 複数メディアのインストーラ
  7. プログラムの追加と削除の項目
  8. 新顔のユーザー
  9. 環境に優しく
  10. XML
  11. COM+ アプリケーション
  12. バージョンごとに

7 SQL

  1. データベースを作成する

8 ユーザー・インタフェイス再び

  1. 一つだけのダイアログ
  2. チューニング・アップ
  3. 相互作用
  4. カスタマイズがいっぱい
  5. これが進捗ですか
  6. よく出来ました
  7. 法律用語
  8. 順番外
  9. 英語はわかりませんか

9 トランスフォーム

  1. インストーラを変形する

10 標準ライブラリ

  1. カスタム・アクションとユーザー・インタフェイス
  2. お静かに願います