EternalWindows
MSI データベース編 / Windows Installer

アプリケーション開発を終えた多くの開発者には、そのアプリケーションを どのようなファイル形式で配布するかという最後の課題が残されています。 比較的容易なのは.zipや.lzhにアプリケーションフォルダを圧縮する方法で、 この方法ならば、ユーザーはファイルを解凍するだけでインストールを完了することができます。 しかし、大規模なアプリケーションになると展開されるファイルの量とサイズは膨大となり、 できれば必要な機能に関するファイル群だけをインストールしたいという要望が ユーザーには生じてくると思われます。 一般にインストーラーと呼ばれるアプリケーションが行う作業は、 必要なファイルのインストールの他、スタートメニューへのショートカットの作成、 アンインストールキーをレジストリに登録するなどがあり、 多くの場合、.exeか.msiのどちらかで配布されることになると思われます。 .msiの拡張子のファイルはMSIファイルと呼ばれ、Visual Studioのセットアッププロジェクトなどで、 次のようなアイコンを持つファイルを作成することができます。

MSIファイルはインストーラーパッケージとも呼ばれ、厳密にはインストーラーではありません。 このファイルにはmsiexec.exeという実行ファイルが関連付けられており、 起動されたmsiexec.exeがMSIファイルに格納されているインストール情報を取得することによって、 インストールが行われるという仕組みになっています。 ただし、msiexec.exeの実装の多くはmsi.dllに依存しており、 事実上のインストール作業はmsi.dllの関数が行っています。 このため、一般のアプリケーションからでもmsi.dllの関数を呼び出せば、 インストールやMSIファイルの編集などの作業を行うことができます。 Windows Installerという言葉は基本的にmsi.dllを扱うアプリケーションを指しますから、 msiexec.exeはもちろんのこと、MSIファイルを作成するツールなどもWindows Installerです。 Windows Installerの関数は、Msiで始まるプレフィックスで始まり、 その種類は大きく次の3つに分けることができると思われます。

種類 特徴
データベース MSIファイルからデータを取得したり設定を行う関数群。 インストールされることになるファイルやディレクトリ構成、 レジストリキーの階層なども解析することができる。
インストール インストールされている機能やファイル群を特定する関数群。 製品の取り扱いを行う。
カスタムアクション インストールが行われるときにロードされるDLLが呼び出す関数群。 自作DLLを指定することで、インストールという作業に独自の処理を追加できる。

MSI(Microsoft Windows Installer)は巨大なトピックであり、 全ての概念、関数を理解することは非常に困難なことだと思われます。 このため、MSIでは上記3つの内容を3章構成として扱い、 本章では、最も理解しておきたいデータベースの部分から説明することにします。 実用性の面を考えた場合、恐らくインストール系の関数に分があると思われますが、 いずれにせよ、MSIファイルの仕組みを理解しないことには本質が見えないため、 まずはデータベース系の関数から取り上げます。

msiexec.exeの仕組み

msiexec.exeは、MSIファイルに関連付けられているにも関わらず、Windows Installerという 表示名を持ったサービスアプリケーションであるという側面を持っています。 サービスのスタートタイプは手動であり、MSIファイルのインストールに伴って起動され、 以後はシステムに常駐することになります。 タスクマネージャ等のアプリケーションでプロセスを列挙すると分かることですが、 MSIファイルのインストール時には、msiexec.exeが2つ起動されています。 1つは、サービスとして起動されたmsiexec.exeですが、 もう1つのmsiexec.exeはどのような意図を持って起動されているのでしょうか。 これは非常に難解な仕組みではありますが、この場を借りて考察することにします。

まず、事実に着目していえることは、MSIファイルのインストール時に表示される ダイアログを閉じた場合、片方のmsiexec.exeは終了するという点です。 これが意味するのは、2つ存在するmsiexec.exeのうち、片方がユーザーインターフェースの 表示や入力処理を行っているということであり、常駐するようになっていないことから、 このmsiexec.exeはサービスとしては実行されてないということになります。 2つのmsiexec.exeは同じ実行ファイルで起動されていながらも実行アカウントは異なっており、 サービスとして起動されているmsiexec.exeはSYSTEMアカウント、ユーザーインターフェース用の msiexec.exeはログオンしているユーザーのアカウントとなっています。 SYSTEMアカウントで実行するmsiexec.exeをサービスであると断定できるのは、 サービスのプロパティでローカルシステムアカウントにチェックが入っていること以外に、 常駐という形態やユーザーインターフェース用を表示しないという性質が、 サービスそのもの特徴と強く一致するという事が挙げられます。

さて、それでは2つ存在するmsiexec.exeのうち、サービス側のmsiexec.exeが行う動作は 何かということになりますが、これはそう簡単には推測することができない問題です。 片方のmsiexec.exeがユーザーインターフェース用であるという見方を貫くならば、 そこで入力されたデータが何らかのプロトコルでサービス側のmsiexec.exeに渡り、 サービス内で実際にインストールを行うという具合になりますが、確証を持つことはできません。 そもそも、msiexec.exeを2つに分ける必要性、即ちサービス内でユーザーインターフェースの表示を 行はない理由が気になるところですが、これは解釈によっては頷けることかもしれません。 サービスがユーザー入力を受け付ける設計になっていると、予期しないデータを受信したことによって、 本来では考えられない処理が実行されることもあり、SYSTEMアカウントで動作しているがために、 不正な処理で生じる被害が拡大しやすくなるからです。 ちなみに、msiexec.exeはサービスのプロパティでデスクトップとの対話を許可しており、 これにより、サービスは対話ウインドウステーション上で実行されることになりますから、 サービス自身でユーザーインターフェースを表示することができないわけではありません。



戻る