Lesson 1 始めよう
2. 中に入れるファイル
次のステップとして、インストールに使用するメディアを指定しなければなりません。 CD と DVD の時代においては、インストール・ファイルを複数のメディアに分ける必要はほとんど有りませんが、 可能性が無いわけではありません (メディアを分ける必要がある場合は、ここで提供されるメディアの Id を使って、個々のディスクを参照することが出来ます。 DiskPrompt は、ユーザーがどのディスクを挿入すべきかを決めることが出来るように、 インストール・メディアのユニットを示すためのいろんなテキスト記述を含むことが出来ます。 Windows Installer はこの記述をディスクのプロンプトとして使用します)。
EmbedCab 属性を使って、インストール・ファイルのキャビネット(アーカイブ)を .msi
パッケージ・ファイル自体の一部として埋め込むか、
それとも独立したファイルにするかを決定することが出来ます。
最終的なインストール・パッケージでは、埋め込みにするのが普通の判断です
(その結果として、単一の自己完結的なファイルが、ダウンロードやメディアでの出荷に供されることになります)。
Cabinet も EmbedCab も指定されない場合は、ソース・ファイルはそのままの状態に留められて、
インストーラの .msi
ファイルと一緒に、配布メディアに直接コピーされることになります。
前書きで強調したように、Windows Installer は以前のプログラム的な手法から宣言的・記述的な手法に移行しました。 私たちは階層的に入れ子になった XML の構造を使って、ソース・フォルダの階層構造を記述します。 そして、インストーラに対して、ユーザー・マシンへのインストールの際に、ソース・フォルダの構造を再作成するように要求します。 Windows Installer は、一番外側のフォルダ、すなわちインストール全体のルート・デスティネーション・フォルダから開始するように私たちに求めます。 ルート・デスティネーション・フォルダは TARGETDIR という定義済みの識別子を持っていて、 これがインストール・パッケージのソース・キャビネット・ファイルまたはソース・ファイル・ツリーを保持するルート・ディレクトリに対置されます。 ソースのルート・ディレクトリも、SourceDir という定義済みの名前を持っています。 この関係が、どこからインストールするか、と、どこへインストールするか、の基本的なリンクを提供します。
このルート・フォルダの内側で、実際の構造について記述を進めます。
インストールされるファイルは、制定されたガイドラインに従って、あらかじめ定められた場所に入っていきます。
たとえば、アプリケーションは \Program Files\Company\Product
の下に入らなければいけません。
ショートカット、デスクトップ・アイコン、ユーザー別設定項目、その他の全てについて、
それぞれにあらかじめ定められたインストール場所が有ります。
好都合なことに、既定のインストール場所全てに対して、インストーラ環境が
定義済みの名前を提供してくれていますので、
それらを参照することは非常に簡単に出来ます
(そして、このことは、私たちを地域化(ローカライゼーション)の問題からも解放してくれます。
と言うのは、英語版以外の Windows では、既定のインストール先フォルダは全く違う地域化された名前を持ち得るからです)。
私たちの現在の例では、三つの定義済みの名前、すなわち、ProgramFilesFolder, ProgramMenuFolder および DesktopFolder を使います。
これらの定義済みの名前はフル・パスを参照することに注意して下さい。
たとえ、デスクトップ・フォルダが C:\Documents and Settings\User\Desktop
という数階層深い場所にあるとしても、
単一の Directory タグだけでそれを参照するのに十分なのです。
しかし、私たち自身の入れ子になったフォルダについては、それぞれのレベルを個別に定義しなければなりません。
全ての要素に対して Id 識別子を提供しなければならないことに注意して下さい (この事は WiX を使用するについて全体にわたって当てはまることです)。 ほとんどの場合、これらの識別子は、WiX のソース・ファイルの至る所から相互参照されるために、一意である必要があります。 ですから、理解しやすい命名規則を用意しておくように気をつけて下さい。 Id として、たとえば ProgramFilesFolder のような、定義済みの名前を使うことが出来る場合もあります。 また、INSTALLDIR のようなプロパティ名(文字列変数とほぼ同じもの)を使う場合もあります。 このプロパティ名については、後でもう一度言及することになります。
コンポーネント(component) の概念とその使い方を支配する規則は、おそらく、Windows Installer テクノロジの最も重要な概念です。 この規則を遵守しないことが、セットアップが失敗する主要な原因です。 従って、最初のサンプルについて先に進む前に、コンポーネントについて十分な理解を得ておくことは、非常に重要な事です。
コンポーネント は、インストールされる事物の最小単元です。 コンポーネントは、常に一つの単位としてインストールされるべき複数のリソース (ファイル、レジストリ・キー、ショートカット、またはその他何でも)から成り立ちます。 あるコンポーネントをインストールするときに、決して、他のコンポーネントに影響を及ぼしてはいけません。 また、あるコンポーネントを削除するときに、決して、他のコンポーネントに害を及ぼしたり、 あるいは、どのコンポーネントにも属さない孤児化したリソースを対象のコンピュータに残したりしてはいけません。 当然の帰結として、コンポーネント間でファイルを共有することは出来ません。 同一の場所にインストールされる同一のファイルが、二つ以上のコンポーネントに含まれることは、決して有ってはいけません。
どういうファイルが製品を構成するかについて考えなければならないのは、コンポーネントのレベルではありません。 ある製品が、一つの EXE と、三つの DLL と、二~三のデータ・ファイルを必要とするとしても、 そのことは、それら全てのファイルが単一のコンポーネントに入らなければならない、という意味ではありません。 全く逆です。後ほど、階層のもっと高いレベルにおいて、どういうコンポーネントが一緒になって製品の独立した部分を形成するかを決定します。
もう一度言います。 コンポーネントは、結びつきが非常に強くて常に一緒にインストールしたり削除したりする必要があるアイテムだけを含むべきです。 もしそれがファイル一個だけを意味するのであれば、コンポーネントはそれぞれファイルを一個だけ含むことになります。 そのようにするのは普通のことであるだけでなく、まさしく、そうするように要求されていることでもあります。 恐がってはいけません。Windows Installer は、数千、いや、必要であれば、それ以上の数のコンポーネントを効率的に処理することが出来ます。
という事で、私たちは一つのコンポーネントに三つのアイテム (一つのファイルと、それを指し示す二つのショートカット)を含めることにします。 コンポーネントは、それ自身の Id 識別子、および、それ自身の一意の GUID を持たなければなりません (WiX のコンパイラとリンカは、この二つのうち、どちらかを間違って再利用すると、警告を発します)。 このことは非常に重要です — これらの GUID は Windows Installer がさまざまなコンポーネントを追跡して記録しておくための唯一の方法です。 このコンポーネントの規則を破ると、悲惨な結果が生じることになります。 例えば、削除時にリソースがどのコンポーネントにも属さない孤児になってマシン上に残されたり、 別のアプリケーションがまだ必要としているのに共有リソースが間違って削除されたり、 既存の製品を再インストールするときに機能の回復に失敗したり、 新しいバージョンのアプリケーションをインストールすると以前のバージョンが破壊されたり、という障害が生じることになります。
ファイルはその名前で特定されます。 実際のファイル名以外に、いくつか別の属性を使って、ファイルの特性を記述することが出来ます。 Vital を no に設定すると、このファイルのインストールは決定的な重要さを持たない、という事をインストーラに教えることが出来ます。 通常は、どのようなファイルであれ、どのような理由であれ、ファイルのインストールが失敗すると、ユーザーが問題を無視することは許されず、 インストールは中止されます。 その他の属性としては、ReadOnly, Hidden, System 等があります。 これらは、すべて、ファイルをインストールするときに適切な属性を設定するためのものです。
すべてのコンポーネントには、キー・パスが必要です。 この項目は、コンポーネントが実際にインストールされているかどうかを Windows Installer が後でチェックするときに使うものです。 まずもってインストールする方法を学習しているという現時点では、これはあまり重要なことだとは思われないかも知れません。 しかし、インストーラのアンインストール機能と修復機能をサポートするためには、 使用する全てのコンポーネントにキー・パスを指定することが重要なことになります。 それに、キー・パスを指定しないとコンパイラが文句を言います …
ショートカットも名前を持っていますが、その他に、作業フォルダやアイコン指定のような他の重要な項目も持っています。
Directory (スタート・メニューやデスクトップのように、ショートカットが配置される場所)と
WorkingDirectory (ショートカットが指し示す場所)との違いに注意して下さい。
後者は任意項目で、省略された場合のデフォルト値は、予想される通り、親のファイルがインストールされるフォルダとなります。
Icon 属性を使うと、実際のファイル名の代りに、ソースのどこか他の場所で定義されている Icon タグの Id を指定することが出来ます
(.exe
という拡張子である必要はないように見えるかも知れませんが、
アイコンの識別子は参照している実際のファイルと同じ拡張子を持っていなければなりません)。
INSTALLDIR というプロパティを再利用していることに気付くと思いますが、これは、予想される通り、
私たちがインストール先にしようとしているフォルダ、すなわち、Program Files\Piyo\Hoge 1.0
を参照します。
その他のフォルダの記述も、後からソース・コードに出てくるかも知れません。
ショートカットは、ノン・アドバタイズド(non-advertised : ショートカットのプロパティ・ダイアログで、 ファイルへの単純なリンクになっているもの)か、アドバタイズド(advertised : リンクがグレイ・アウトされているもの)かを選べます。 第二の形式の場合は、ショートカットが指し示すファイルが欠けているときに、 Windows Installer が修復インストールをしてファイルを修復することが出来ます。
さらに二つ、一意の Id と Guid を持つ別のコンポーネントを定義します。
あなたが予想される通り、数百さらには数千のファイルを持つアプリケーションにとっては、 このようなやり方は、数百または数千のコンポーネントが必要になる、という事を意味します。 そうです、それが普通であり、それが期待されている方法なのです。 恐がることはありません。パフォーマンス上の問題は生じません。 Windows Installer はこのやり方で問題なく動作するように作られています。
そういう数百または数千のコンポーネントを WiX ソース・ファイルに打ち込むということは、 もちろん、もう一つ別の困難な課題を提起するものです。 ツールセットには、この事に関して支援をする小さなユーティリティーがあります(後で詳細に述べます)が、 本当の解決は、考え方を変更することにあります。 セットアップ・プログラムはメインのアプリケーションがほとんど完成した時に大急ぎで書くべき独立したアプリケーションである、 という考え方をやめるのです。 WiX のソース・ファイルも、ツールセット自体も、開発環境に統合することが容易に出来るのですから、常に同期状態を保つべきです。 新しいモジュールの開発に着手したり、新しいレジストリ参照をプログラムに追加したりしたら、 ただちに、対応する WiX ソース・ファイルを同時に修正するのです。 そうすれば、セットアップはアプリケーション自体と一緒に完成されて、 後からインストールに必要なすべてのファイルとその他の情報の断片を抽出する必要が無くなります。 WiX プロジェクトはモジュラー化できます(後で詳細に述べます)ので、この手法は、一人の開発者ではなく、 大きなチームでアプリケーションを開発する場合でも、うまく機能します。
そして、次に、ディレクトリ要素を閉じるタグが来ます — まだ終りではありませんので、開始のタグより一つ少なくします。 最初の TARGETDIR ディレクトリの内側にとどまって、あと二つ、インストーラの定義済みの名前を使ってフル・パスのフォルダを定義します。 一つはスタート・メニューのショートカットのためであり、もう一つはデスクトップ・アイコンのためです。 その後で、ようやく、一番外側の Directory タグが閉じられます。
製品がアンインストールされるときにプログラム・フォルダを削除する必要がありますので、第四のコンポーネントを作成する必要があります。 RemoveFolder タグが私たちの意図を記述します。 On 属性によってフォルダが削除される時が決定されます(使用できる値は、install, uninstall および both です)。 既に述べたように、すべてのコンポーネントは自分自身のキー・パスを持たなければなりません。 この場合、キー・パスは追加の RegistryValue タグです。 このタグは、この最初のレッスンの範囲を超えていますので、後でもう一度説明します。 KeyPath 属性をコンポーネントかフォルダに設定してもうまく機能するかも知れませんが、リンカが警告を発する結果になります。 ですから、当面、コンパイラとリンカの警告メッセージを避けるために、一時的に説明抜きで、この解決方法を受け入れておいて下さい。
これら二つのフォルダを特定するのに使用した Id 識別子(ProgramMenuDir
と DesktopFolder
)に注意して下さい。
これらは、前に、ショートカットの Directory 属性として使用した名前であり、ショートカットの場所を実際のフォルダに関連づけたものです。
最後に、しかし重要なこととして、私たちがどんな機能をインストールしたいのかを、インストーラに指示します。 機能(Feature)はアプリケーションの独立した部分であり、インストールするかしないかを選ぶように私たちがユーザーに提案するものです。 詳細はもちろん特定のソフトウェア・パッケージに依存しますが、通常の組合せは以下のようなものになります。
- プログラムの機能に必要な基本的な実行プログラム
- 説明書、ヘルプ・ファイル
- チュートリアル、サンプル・ファイル
- 関連するユーティリティー
最初のサンプルでは、そのような機能分けはしません。 まず、インストールしようとする三つのファイルをいろんな機能に分割することはほとんど不可能です。 次に、機能を分けるためには、ユーザーが機能を ON/OFF するためのユーザー・インタフェイスも必要になります。 これについては次回のレッスンで説明しますが、今のところは、機能は一つにしておきます(というのは、少なくとも一つは機能が必要だからです)。 この機能としてインストールしたいコンポーネントを Id 識別子を使って参照します。
ショートカットに使用したいアイコンも含めなければなりません。
アイコンの Id 識別子は、対象のファイルと同じ拡張子、この場合は、.exe
を持たなければならないことに注意して下さい。
このようにすると、ソース・ファイルは最終のインストーラ・パッケージの中で、独立して保存されます
(つまり、メインの実行ファイルを参照している場合、二つのコピーが保存されます)。
ファイルのサイズが大きすぎて問題になる場合は、アイコンだけを含んだ小さな .exe
か .ico
を作成して下さい。
以上で、残されていることは、まだ開いている二つのタグに、閉じるタグを提供することだけになりました。
行った作業を要約しましょう。 最初に、人間が読めるテキストと要求される GUID の両方で、私たちのアプリケーションの記述を行いました。 第二に、インストールに使いたいメディアを定義しました。 次に、インストールされるファイルのフォルダ構造を定義しました。 インストールされるファイルは、付随するリソースと一緒に、すべて適切なコンポーネントに入れました。 そして最後に、個々のコンポーネントを参照して、インストールしたい機能を記述しました。