はじめに
前回は、Windows Installerが標準提供するシリアル番号の検証ルーチンを用いてチェックを行いました。今回はこの部分を独自に検証するルーチンに置き換えます。
過去の回
- 第1回:Windows Installer XML(WiX) toolsetを利用したmsiの作成
- 第2回:簡易ユーザーインターフェイスを持つインストーラの作成
- 第3回:カスタムインストールに対応したインストーラの作成
- 第4回:ユーザー情報入力画面の作成とシリアル番号の検証
対象読者
インストーラを必要とするすべての開発者。
必要な環境
連載では、WiX 2.0.4103.0以降を対象としていますが、原則として原稿執筆時点での最新版を利用しています。
原稿執筆時(2006/11/17)の最新ビルドは2.0.4611.0となっています。また、独自の検証ルーチンの作成には Visual C++ 2005 Express Edition(以下、VC2005)または、Visual Studio 2005 Standard Edition(以下、VS2005)以上が必要となります。
開発環境の準備
詳細は第1回で詳しく書いているので、そちらを参照ください。なお、今回はDLLを作成するため、VC2005(あるいはVS2005)を必要とします。
独自検証手段の実装
第4回で作成した標準の検証機構から、独自の基準に基づくシリアル番号検証機構へと変更します。まずは、何よりも先に独自のシリアル番号を取り決めなければなりません。今回は前回と同様、数字の3桁-7桁という構成にしますが、数字として有効なものは、1、2、3のいずれかの数値のみとします(詳細は後述)。これだけでも既にValidateProductIDではチェックしきれないものとなっていますので、何らかの形で独自の検証手段を盛り込む必要があります。
カスタムアクションの作成
Windows Installerでは上記のような独自の動作をカスタムアクション(Custom Actions)と呼びます。これに対しValidateProductIDのようにあらかじめ組み込まれている動作はStandard Actionsと呼ばれます(標準動作や標準処理などと呼ばれることもあります)。まずはカスタムアクションの実装可能形式を見てみることにしましょう。
カスタムアクションの実装形式
カスタムアクションの実装形式は、なんらかのプログラム実装を伴う3つ(DLL、EXE、WSH)の形式、プロパティまたはディレクトリプロパティの設定、エラーメッセージの表示、ネストインストールの実行(インストールまたはアンインストール)と6種類用意されています。このほかに、実行するファイルの格納場所、実行のタイミング、実行方法、戻り値のチェックなどなどすべてを組み合わせていくと実に数十種類もの組み合わせが用意されています(専用ページが用意されている代表的なものだけでも、20ある)。
残念ながら、このうちネストインストール(メジャーアップグレードは含みません)だけは、WiXではサポートされていませんが、残りの形式はすべてサポートしています。ちょっと説明が長くなってしまいますが、詳しい資料がありませんので、簡単に6種類の実装について説明しておきたいと思います。
プロパティ設定(ディレクトリプロパティ設定)
インストール先のパスを設定する、デフォルトのインストール先をインストール済み製品と一致させるなど、インストーラ作成時点では確定することができないものを指定する場合に利用します。
ARPINSTALLLOCATIONなど、インストール先の実パスを指定しなければならないプロパティなどの設定はこのカスタムアクションを利用して設定します。また、カスタムアクションのうち、Deferred(遅延実行)、Commit(コミット実行)、Rollback(ロールバック実行)に分類されるカスタムアクション(DLL/WSH形式の場合のみ)に詳細情報を渡す際にも利用されます(詳しくは、Obtaining Context Information for Deferred Execution Custom Actionsを参照ください)。
エラーメッセージの表示
インストーラの実行中に、何らかの理由で処理を続行できない状況が発生した場合など、主にUIモードの実行中に利用します。専用のエラーメッセージダイアログを用意するという方法もありますが、その場合、作成の手間がかかるばかりになるため、単純にメッセージボックスを出して終了したいだけという場合などで利用されています。
あまり多くの場面で使われるものではありませんが、メジャーアップグレードなどを行う際に、起動時の簡単なチェックだけでは調べきれないものがある場面でよく利用されています。
ネストインストール
製品間で共通利用するシステムコンポーネントなどを、製品のインストーラとは別に用意して、製品のインストール中にインストールする(大抵の場合、恒久的にインストールされたままの状態となる)ための特別なインストール形式として用意されています。
通常、このような共通コンポーネントはマージモジュールとして提供されることが多いのですが、インストーラとして独立させることによるメリットもあるため、用意されています。ですが、ネストインストールは、実行条件の制約が非常に厳しいため、どのようなものにでも適用できるとは限らない(特に、インストール条件の詳細に強い影響を受けてしまう)ため、インストーラの作成そのものが非常に複雑になってしまうというデメリットがあり、あまり利用されていません(こういった、複雑性を助長する方向に向けないためなのか、WiXでもサポートされていません)。
最近では、このような独立インストーラとして提供しているものは、事前インストール(ブートストラッパー(setup.exe)が製品本体のインストーラを実行する前に必要なものとしてインストールしてしまう)を行なったり、事後(製品インストーラの完了画面の後など)に実行するなどのスタイルがとられていることがほとんどです。
EXE形式
EXE(原則としてUIを持たないWindowsアプリ形式)を実行するカスタムアクションです。自己完結型のカスタムアクションの実装や、インストール後にアプリケーションを起動するなど(動作スタイル的にはカスタムアクションとは見られませんが、Windows Installerではカスタムアクションとして実装されます)で利用されています。
インストーラからEXEへの情報供給が起動パラメータのみ、EXE側からインストーラへのフィードバックは、終了コードだけとなるため、カスタムアクション自身が自己完結できる形式でのみ利用できるという制限があるものの、データベースのテーブル作成のように、成功or失敗しかないようなものなどでよく利用されています。また、カスタムアクションとしては唯一完全独立実行型となるため、事前に独自の単体テストが行えるという大変大きなメリットもあります(他の形式はすべて、単体で実行することが困難あるいは不可能な形となっています)。また、EXE形式は必ず独自の実行プロセス(通常のEXE実行と同様)を持つため、パフォーマンス的に不利な点があるということを覚えておくとよいかと思います。
WSH形式
WSH(Windows Scripting Host)を利用した、スクリプトを実行するカスタムアクションです。Windows Installerでは、VBScriptとJScriptの2つの形式をサポートしています(64bit版OSであれば、64bitモードでの実行もサポートしています)。
スタンドアロンで動作するWSHとは異なり、Windows Installer自身がホストとなるため、アプリケーションクラスに当たるオブジェクトもインストーラのオブジェクトとなります。専用の開発環境(コンパイラなど)が不要なため開発の敷居が低いという利点はあるものの、アンチウィルスソフトに実行を阻害されることがある、WSHのランタイム(5.6以上が必要)がインストールされていない環境では実行できないということからあまり推奨されてはいません。また、スクリプトの特性上、素のテキストデータを保持することになるため、中のアルゴリズムが丸見えになるというデメリットも持っています。
DLL形式
32bitまたは実行環境のアーキテクチャと同じ64bit形式のNativeDLL(.NET Frameworkを利用しないDLL)を実行するカスタムアクションです。一般にカスタムアクションと言えば、この形式といわれるほど利用数が多く、ネストインストールとエラーメッセージの表示以外のすべてのカスタムアクションがこの形式で(WSHでも実質的には同じ)実装することができます。
WSHとは異なりスクリプトではないため、アンチウィルスソフトがブロックしてしまうこともなく、また、実行時にコンパイルされることがないため、実装が丸見えになるということもありません。利用可能範囲も多岐にわたっており、実質的にはインストーラ内から呼び出し可能な箇所であれば、ほぼどこにでも適用することができると言えるほど、あちこちで利用することができます(部分的であれば、UIでさえ実装できてしまう)。ただし、デメリットがまったくないわけではなく、この形式での実装は、必ず「UINT APIENTRY FuncName( MSIHANDLE );
」というC関数形式でのエクスポート関数の提供が必要とされているため、コンパイラもある程度限定されてしまいます(VB6のようにDLLはCOMしか作れないものは利用できない)。また、.NET Frameworkのホストもされないため、.NET Frameworkも利用できません。
Windows Installerではこのような事態を避けるため、カスタムアクションでのメッセージボックスの表示を肩代わりできるMsiProcessMessageという専用のAPIを用意しています。これを使うことで、通常多くのカスタムアクションが差し込まれる実行シーケンスでは、必要に応じてメッセージボックスを表示することができるようになっています(そのほかにもファイルの利用中を表示したり、インジケータを制御したり、キャンセルボタンを一時的に無効化させるなど、プログラム側からUIを制御するさまざまな機能が備わっています)。が、残念ながらこのAPIは、ダイアログの中から呼ばれた場合は、利用することができません。呼び出しは問題ないのですが、何もせずすぐにリターンしてきます(戻り値0で判定可能)。そのため、ダイアログからの呼び出しでのメッセージ表示は、必ず、別のダイアログとして作成しなければならない仕組みになっています(多くのサンプルがこの仕組みを踏襲していないため、参考になるものが少ないのですが、サンプルも兼ねて実装しています)。
これとは別に、DLL形式やWSH形式はインストーラのプロセスで動作するとはいえ、実行形式によってはプロパティはおろかフォルダ情報すらそのままでは参照できないということがあります(動作だけで見れば実装形態が異なるEXE実行と同様)。今回はこれらについて詳しいことは記載しませんが、プロパティ設定のところに記載したリンク先に詳しいことが書かれていますので、さまざまなカスタムアクションの実装を検討している場合は、必ずこのドキュメントに目を通してもらいたいと思います。
実装形式の検討
上述したカスタムアクションのうち、プロパティ設定やエラーメッセージ、あるいはネストインストールでは、さすがにシリアル番号を検証するということはできません。従って、EXE/DLL/WSHのいずれかを選ぶことになります。
何らかの形でインストーラへのフィードバックを必要としますし、インストーラを終了してしまうのはまずい状況(このあと実際に動かしてみますので、後ほどサンプルソースを参照してもらいたいと思います)もありますので、EXEではいささか力不足と言えます。
また、WSHは万が一スクリプトの実行がブロックされてしまうと、NGが検出されずに続行してしまう可能性があります(ブロックされた場合、スクリプトエンジンが成功終了になってしまうため、インストーラは成功したと判断します)。これはある種想定外の動作であるとはいえ、事例としてある以上、想定しておかざるを得ないのが実情です。
従って、インストーラとやり取りでき、外的要因で実行されないという状況が発生しないのは、DLL形式だけとなってしまいます。消去法的な考え方ではありますが、今回はDLLを使ってカスタムアクションを実装したいと思います。