Windows Installer技術が発表される以前はアプリケーションをインストールするためにしなければならないこと(どこそこのレジストリに書き込まなければならないとか)やガイドライン(アプリケーションはProgram Filesフォルダの中にインストールするとか)は存在したものの、それをどのように実装するかは個々のディベロッパーに任されていました。多くの場合開発者は独自にセットアッププログラムを開発したり、InstallShieldに代表されるインストーラ作成ツールを使用してインストーラを作成していました。その帰結としてインストールの手法は製品によって千差万別となり、このことがさまざまなトラブルの原因となっていました。まずインストーラのバグが多かったり、製品によってはアンインストールがうまくいかないことがあったり、中にはシステムの設定を勝手に変更してしまい、しかもアンインストールをしても元に戻らないかったりするものもありました。また、Windows OSの仕様のほうが後から変わってしまってインストーラが対応できないということもありました。InstallShieldのようなインストーラ作成のための専用ツールを使用して作られたインストーラは比較的「まし」だったとはいえ、それでもトラブルはつきものでした。
※Windows 95からコントロールパネルに「アプリケーションの追加と削除」アプレットが加わり、そこからアンインストーラを起動できるようになっていますが、これは単にアンインストーラを統一的に起動する仕組みに過ぎず、起動されるものが何であるかまでは関知しないものです。
InstallShieldは専用のスクリプト言語(InstallScript)を使用してインストールの手順を記述していくことで比較的容易にインストーラを作成を可能にするツールでした。たとえばファイルをコピーしたりレジストリにデータを書き込む場合でも、直接Windows APIを呼び出すのではなくInstallScriptのコマンドを使って記述していきます。(InstallScript自体はC言語の構文によく似たところがあります。)これによりシステムに対して行われる変更がすべて把握できることとなり、その情報を元にInstallShieldはアンインストーラを自動的に作成することができました。(つまり、行った変更と逆のことをやればいいわけです。)スクリプトではインストール先のシステムに応じた条件分岐も行われるので実際に行われる処理は一本調子ではないのですが(あるマシンではAファイルをコピーし、別のマシンではすでに存在するのでコピーしないなど)システムに変更を加えるコマンドをそれが実行される順番で記録していくことでその逆の操作手順を自動的に生成するというのはそれはそれですごい技術でした。
しかしながら現実にはそのInstallScriptを実行するInstallShieldのエンジン自体のバグに苦しめられた開発者(もしくはユーザーサポート担当者)は決して少なくありませんでした。特定のユーザーでは訳の分からないランタイムエラーが発生することも珍しくなく、その原因がInstallScriptの記述ミスによるものならあきらめもつくし(?)対策も立てやすかったのですが、むしろInstallShield自体の日本語への対応が不十分であったりエンジン自体のバグ、環境が変わったためにエンジンが起動しないなど、エンジンがらみのトラブルのほうが多く、サポートする側も対策方法が分からずに困惑してしまうこともよくありました。
ソフトウエアのインストールは程度の差はあれシステムに変更を加えるものである以上、どのような処理をしているか分からないブラックボックス的なインストーラではセキュリティ上でも不安があります。つまりシステムの管理者はインストーラを起動する前からそのインストーラがどのような変更をシステムに対して加えるかを知ることができるというのが理想です。そのような野心的な目的の実現のためには従来の手続き記述型の言語を使ったインストーラの作成手法(スクリプトベース)から、データを中心とした(マイクロソフトの言うところの「データドリブン」な)作成手法へとシフトすることが必要でした。
以下はマイクロソフトのホームページからの引用です。
"従来のスクリプトベースのインストールでは、特定のアプリケーションをインストールする命令がインストールプログラムに用意されます。このようなハードコード化した一連命令は、単発的なインストールには有効ですが、新規のアプリケーションや新しいバージョンのインストール、アンインストール、または再インストールを連続的に実行する場合は問題に、発生しやすくなります。また、セットアップスクリプト間で情報が共有されないため、エンドユーザーや管理者にとって、インストールしたアプリケーションを追跡管理することが困難になります。新しいデータ ドリブン型の Windows Installerは、インストール スクリプトが原因で発生する多くの問題に対処しています。データ ドリブンインストール モデルでは、開発者がインストール テーブルのマスターセットを作成し、すべてのアプリケーションのリソース (ファイル、レジストリキーなど)をコンポーネントやサポートされる機能と明確に関連付けます。これらのテーブルを作成するときは、どのようにインストールするかよりも、なにをインストールするかに焦点を合わせます。インストールするオブジェクトとインストールする場所を開発者が指定し、Windows Installer が手続きの命令を管理します。"
Windows Installerでインストールを行う上での主体となるファイルはmsiという拡張子を持つデータベースファイルになります。msiファイルにはすべてのデータが役割が明確に定義されたデータベースのテーブルの中に入っています。インストールはWindows Installerエンジンがこのデータベースファイルを読み込み、そのデータに基づいて実際の処理を行うことで実行されます。カスタムアクションという例外を除けばmsiファイルの中に実行コードは含まれません。msiファイルはMicrosoft Accessが使用するmdbファイル(JETデータベースファイル)やExcelのブックのようなものだと思えばよいでしょう。(技術的にはmsiファイルの形式は「COM構造化ストレージファイル」と呼ばれるものです。)
Windows Installer技術のメリットは他にも
など色々ありますが別にWindows Installerの宣伝をするつもりはないのでこの辺でやめておきます。
※一つ注意しておかなければならないのはWindows Installerはオープンアーキテクチャーであるため、Windows Installerの仕組みを知っている人ならだれでもインストールのシーケンスを変えてしまうことができるということです。そのためたとえばインストール時にシリアル番号のチェックを行っているような場合でも、そのチェックを飛ばしてインストールを完了させてしまうことも可能です。よってシリアル番号の妥当性チェックはインストーラだけに一任せず、アプリケーション自身でも行う必要があります。
Windows Installer技術の発表はそれまでInstallShield社の独自技術に悩まされていたインストーラ開発者にとって福音でした。しかしながら従来の資産はWindows Installerと互換性がないため、Windows Installerの恩恵を受けるためには既存のインストーラを新たに作り直す必要があり、これが新たな悩みの種となりました。InstallShield社は従来通りの独自技術に基づく製品を継続すると同時に、新たにInstallShield (Professional) for Windows Installer Editionを発表します。その後はっきりと二系統の製品シリーズ(Professional v.s. Developer)に別れ、最近までそれが続くことになります。すでにInstallShieldでインストーラを開発していたところは、このどちらか(または過去の遺産もそのまま継承し新規開発ではWindows Installerを採用するなら両方)のシリーズを購入するという選択を迫られました。
InstallScriptはInstallShieldのWindows Installer対応版で無くなったかというとそうではなく、InstallShield Professional for Windows Installer Edition 2.0まではカスタムアクションとしてInstallScriptを実行することができるようになっていました。カスタムアクションとしてはもともとVBScriptやJScriptで書かれたスクリプトを実行できるのですがこのときのInstallScriptはそれをパワーアップ†したものといえ、従来のようにインストール全体の流れをコントロールするといった使われ方とはかなり異なります。InstallShield Developer 7からWindows Installer本来の処理フローを変更することによって従来のInstallShieldでのInstallScriptの使い方に近づけています。このInstallShield独自の方式によるものと「標準プロジェクト」、Windows Installer本来の方式によるものを「基本msiプロジェクト」と(InstallShieldの中では)呼んでいます。(私に言わせれば「基本msiプロジェクト」のほうが「標準」だと思うのですが。基本と標準の違いが分かりにくいので後者に「msi」と付けているようにも思えます。)
†パワーアップ: VBScriptでもCOMオブジェクトを呼び出せばほとんどどんなことでもできますが、InstallScriptでは言語自体にインストール時に必要となる多くの機能が最初から組み込まれているという意味でのことです。なおVBScriptを使うにはシステムにWindows Script Hostがインストールされている必要があります。
※InstallShield社の独自技術はトラブルの元なのでできるだけやめて欲しいものです。しかしながら従来のインストーラでできていたことがWindows Installer対応版だと(簡単には)できなくなるというのでは製品戦略上まずいので何とか実現しようという努力は理解できます。とはいえ普通にソフトウエアをインストールする分には「基本msiプロジェクト」(+DLLで作成するカスタムアクション)で大抵間に合うのも事実です。
ちなみに、「基本msiプロジェクト」では
setup.exe → msiexec.exe (→ IDriver.exe)
と処理が移されます。カッコ内はカスタムアクションでInstallScriptを呼び出した場合です。一方「標準プロジェクト」では
setup.exe → IDriver.exe → msiexec.exe
という流れになります。msiexec.exe はWindows Installerのエンジン、IDriver.exeはInstallScriptを動かすエンジンです。
ちなみに当社では当時数本のパッケージソフトを抱えていましたが、早い時期にWindows Installer形式ですべてのインストーラを作り直しました。その結果、エンドユーザーでのインストールのトラブルは激減し大いに助かりました。
日本ではWindows Installerに関する資料が少ないためかWindows Installerへの移行はすぐには進まなかったように思います。また初期のInstallShield for Windows Installer にも色々とバグがあり、それがWindows Installerのバグと誤解されたことも一因となっているとしたら残念なことです。 →「InstallShieldにあった不具合等」
そもそもインストーラはユーザーのシステムがソフトウエアのインストールに適したものであるかを判断し、適さなければその旨をユーザーに告知するという使命も持っています。そのため特定のユーザーのマシン環境や新しいOSで動かないといったことにならないよう努めなければなりません。もしInstallScriptのエンジンが新しいWindows OSで動かなかったとしたらInstallShield社は新しいエンジンをリリースするでしょうが、すでに配布されている古いインストーラに関してはどうすることもできません。またInstallScriptは動かなくともインストールするアプリケーション自体はそのOSでも問題なく動くとしたらこんなばかばかしいことはありません。
Windows Installerにはその機能を拡張するためにカスタムアクションといって開発者が独自に作成したDLLを呼び出したり、アプリケーションを起動したりといった機能があります。このカスタムアクションを使えばWindows Installerエンジンを通さずに直接レジストリを変更したり、ファイルのコピーなども実行することも可能です。このことはカスタムアクションを乱用すればWindows Installerが導入された本来の目的を反故にし、従来のインストーラ技術で起こり得たあらゆる問題を再発させる可能性があることを意味します。カスタムアクションはWindows Installerの本来の機能では足りない部分を補うためにあるのだと思いますが、その拡張性に制限がほとんどなく、どの程度の利用に留めておくかは開発者に任されています。Microsoftはカスタムアクションの使用をほどほどにせよとはあえて唱えていませんが、Windows Installerのベース機能では足りないからといってやたらと拡張するのではなく、まずはできる範囲で工夫するよう努めるべきだと思います。