ファイル拡張子の関連付け
インストーラーで最もよく使われるレジストリは、ファイル拡張子の関連付けではないかと思います。
基本
プログラムをインストールする際、そのプログラムのデータファイルをダブルクリックしたときにプログラムを起動してデータを読ませるよう設定する、という要求はよくあります。関連付けはレジストリに書き込みます。例えば、プログラムyourapp.exe
が拡張子.papa
というデータファイルを使用するなら、次のようになります。
HKEY_CLASSES_ROOT
+ .papa
| + (Default) = YourProgID
+ YourProgID
| + shell
| + open
| + command
| + (Default) = "fullpath\yourapp.exe" "%1"
ここで、YourProgID
は[Vendor or Application].[Component].[Version]
といった形式が推奨されています。全体的な情報は、Application RegistrationやFile Typesあたりから読み進めていけば一通り得られます。例えばWiXでは、下記のようなソースで表現できます。このコードで、プログラムprTxtA
のデータファイルとして、拡張子.papa
のファイルを関連付けます。
1: <?define prgid="prTxtA.extcmd.1"?>
2:
3: <Component Id="prgCompo" Guid="956fe4e0-24eb-4e2f-89c4-18fd051f216e">
4: <File Id="prTxExeFile" KeyPath="yes" Source="..\prTxtA_SRC\prTxtA.exe" />
5: <RegistryValue Id="extRegv" Root="HKCR" Key=".papa" Type="string" Value="$(var.prgid)" />
6: <RegistryValue Id="comRegv" Root="HKCR" Key="$(var.prgid)\shell\open\command" Type="string" Value=""[#prTxExeFile]" "%1"" />
7: :
8: :
9: </Component>
基本はこれで良いのですが、ちょっとした落とし穴があります。
他のアプリと利用する拡張子がかぶる
よく使われるメジャーなデータ形式は色々なアプリが拡張子の関連付けを奪い合います。また、同じアプリの異なるバージョンを一つのPCで利用できるケースもあり、どのように拡張子の関連付けを管理していくか悩むところです。先の基本で例示したレジストリ構造を見れば分かるように、何も考えずにすでに関連付け済みの拡張子に関連付けをすると、古い関連付けの情報は消えてしまいます。そこでまず、この部分
HKEY_CLASSES_ROOT
+ .papa
| + (Default) = YourProgID
さらにWindowsには、ファイルアイコンを右クリックするとメニューに現れる「プログラムから開く」や、「ファイルの種類ごとに既定のアプリを選ぶ」機能があります。ここにインストールしたアプリを一覧表示させることで、容易にユーザーが拡張子の関連付けを変更できるようになります。下記のように、拡張子のキーの下にOpenWithProgids
キーを置くことで実現します。これは、prTxtAとprTxtBの2つのアプリをインストールした後の状態を示します。
HKEY_CLASSES_ROOT
+ .papa
| + (Default) = prTxtB.extcmd.1
| + OpenWithProgids
| + prTxtA.extcmd.1 = ""
| + prTxtB.extcmd.1 = ""
+ prTxtA.extcmd.1
| + shell
| + open
| + command
| + (Default) = "fullpath\prTxtA.exe" "%1"
+ prTxtB.extcmd.1
| + shell
| + open
| + command
| + (Default) = "fullpath\prTxtB.exe" "%1"
こうすると一覧から自分のアプリを容易に選べるようになります。
削除されないレジストリ(やファイル)をインストールする最も簡単な方法はComponentにPermanent属性を付けることでしょう。下記のソースのように削除しないレジストリを別のComponentに切り出せば実現できます。アンインストールすると実体のないProgIDが残ることになりますが、ProgIDが登録されていない場合は無視されるので問題ありません。ただし気を付けなければいけないのは、ComponentにPermanent属性を付けると、アンインストールしても環境にComponentの登録情報が残ることです。インストーラーのテストの都合でComponentの登録情報を削除する場合は、手動でレジストリから情報を消す必要があります。
1: <?define prgid="prTxtA.extcmd.1"?>
2:
3: <Component Id ="extCompo" Permanent="yes" Guid="bcadce47-ae51-4ad1-9391-227c998dea85">
4: <RegistryValue Id="extReg" Root="HKCR" Key=".papa" Type="string" Value="$(var.prgid)" KeyPath="yes" />
5: </Component>
6: <Component Id="prgCompo" Guid="a5c70bd9-9158-4c0c-b8f4-4376bbc6e1fb">
7: <File Id="prTxExeFile" KeyPath="yes" Source="..\prTxtA_SRC\prTxtA.exe" />
8: <RegistryValue Id="openwithReg" Root="HKCR" Key=".papa\OpenWithProgids" Type="string" Name="$(var.prgid)" Value="" />
9: <RegistryValue Id="comRegv" Root="HKCR" Key="$(var.prgid)\shell\open\command" Type="string" Value=""[#prTxExeFile]" "%1"" />
10: :
11: :
12: </Component>
アイコン画像をデータファイルに割り当てる
MSDN Libraryの情報では、Programmatic Identifiersが参考になります。
- アイコンファイルに割り当てる場合
progIDのキーの下にDefaultIconキーを置き、下記のようにアイコンファイルへのパスを記述します。
HKEY_CLASSES_ROOT
+ YourProgID
| + DefaultIcon
| + (Default) = fullpath\blueData.ico
WiXのソースは、例えば下記のようになります。
1: <?define prgid="prTxtA.extcmd.1"?>
2:
3: <Component Id="prgCompo" Guid="a5c70bd9-9158-4c0c-b8f4-4376bbc6e1fb">
4: :
5: :
6: <File Id="iconFile" Source="blueData.ico" />
7: <RegistryValue Id="iconReg" Root="HKCR" Key="$(var.prgid)\DefaultIcon" Type="string" Value=""[$prgCompo]\blueData.ico"" />
8: </Component>
- EXE,DLLのリソース中にあるアイコン画像を使う場合
ファイル名の後に何番目(0が1番目)のアイコンか指定します。例えば、リソースの2番目のアイコン画像を使うなら、次のようになります(DLLの場合も同じ書式です)。
HKEY_CLASSES_ROOT
+ YourProgID
| + DefaultIcon
| + (Default) = fullpath\prTxtA.exe,1
WiXのソースは、例えば下記のようになります。
1: <?define prgid="prTxtA.extcmd.1"?>
2:
3: <Component Id="prgCompo" Guid="387e3686-06e3-4cdf-9992-9c8ea7da56bc">
4: :
5: :
6: <File Id="prTxExeFile" KeyPath="yes" Source="..\prTxtA_SRC\prTxtA.exe" />
7: <RegistryValue Id="iconReg" Root="HKCR" Key="$(var.prgid)\DefaultIcon" Type="string" Value="[$prgCompo]\prTxtA.exe,1" />
8: </Component>
[#prTxExeFile]や[$prgCompo]などの表現の意味
これまで何の説明もなくWiXのソースに使ってきましたが、これらはMSIの機能です。[#prTxExeFile]
は、prTxExeFileというIdで定義したファイルへのフルパスを示します。[$prgCompo]
は、prgCompoというIdで定義したコンポーネントのフォルダ・パスを示します。これらはインストールの実行時に値が入れられるのでパスをハード・コーディングするよりは良い方法です。
パスを表現する方法
環境変数を使ってパスを指し示す方法もあります。