ダイアログボックスのデザインとMSIファイルの関係
Windows Installerでは、ユーザーにウィザード形式でダイアログボックスを表示して、インストールに関する情報を表示・設定します。このダイアログボックスのデザインは、古典的なWindows標準のUI部品が使用されます1が、ウィンドウ上の文章やボタンの配置などUI部品を自由に設計可能で、その設計情報はMSIファイル内にいくつかのテーブルに分散して格納されています。この格納方法が決して分かりやすいものではないため、ダイアログのデザインはWiX Toolsetなどのツール側に用意されたものを、必要に応じて改造しながら使用するのが賢いやり方2です。ただ、UI部品の情報がどのようにMSIファイルのテーブルに格納されているか知ることで、改造が容易になり、凝ったUIの表示も可能になります。
今回はこのような事情もあって、Windows Installerが扱えるUIの説明の入り口として、WiX ToolsetでUIをカスタマイズする方法を説明します。
WiX ToolsetのUIセット
WiX Toolsetには、いくつかのダイアログボックスの画面デザインと、これらの表示順を規定したDialog Setが用意されています。これらのダイアログは、WiX Toolsetのソースに含まれるファイルを改造することで自由にデザインを変更できます。ダイアログ関連のソースファイルは、WiX Toolsetのダウンロードページ(WiX Toolset公式ページのDownloadsにダウンロードページのリンクがあります。)にあるSource code
(wix3-wixXXXrtm.zip または wix3-wixXXXrtm.tar.gz。XXXは数字、執筆時点のファイル名はwix3-wix3112rtm.zip
およびwix3-wix3112rtm.tar.gz
でした)を解凍すると、src\ext\UIExtension\wixlib
フォルダ以下に格納されています。ここにあるファイルを簡単に分類すると下表のようになっています。
Dialog Set | Dialogs | Localization File |
---|---|---|
WixUI_Advanced.wxs WixUI_FeatureTree.wxs WixUI_InstallDir.wxs WixUI_Minimal.wxs WixUI_Mondo.wxs |
AdvancedWelcomeEulaDlg.wxs BrowseDlg.wxs CancelDlg.wxs CustomizeDlg.wxs DiskCostDlg.wxs ErrorDlg.wxs ErrorProgressText.wxs ExitDialog.wxs FatalError.wxs FeaturesDlg.wxs FilesInUse.wxs InstallDirDlg.wxs InstallScopeDlg.wxs InvalidDirDlg.wxs LicenseAgreementDlg.wxs MaintenanceTypeDlg.wxs MaintenanceWelcomeDlg.wxs MsiRMFilesInUse.wxs OutOfDiskDlg.wxs OutOfRbDiskDlg.wxs PrepareDlg.wxs ProgressDlg.wxs ResumeDlg.wxs SetupTypeDlg.wxs UserExit.wxs VerifyReadyDlg.wxs WaitForCostingDlg.wxs WelcomeDlg.wxs WelcomeEulaDlg.wxs |
WixUI_ar-SA.wxl WixUI_bg-BG.wxl WixUI_ca-ES.wxl WixUI_cs-CZ.wxl WixUI_da-DK.wxl WixUI_de-de.wxl WixUI_el-GR.wxl WixUI_en-us.wxl WixUI_es-es.wxl WixUI_et-EE.wxl WixUI_fi-FI.wxl WixUI_fr-fr.wxl WixUI_he-IL.wxl WixUI_hi-IN.wxl WixUI_hr-HR.wxl WixUI_hu-HU.wxl WixUI_it-it.wxl WixUI_ja-jp.wxl WixUI_kk-KZ.wxl WixUI_ko-KR.wxl WixUI_lt-LT.wxl WixUI_lv-LV.wxl WixUI_nb-NO.wxl WixUI_nl-NL.wxl WixUI_pl-pl.wxl WixUI_pt-BR.wxl WixUI_pt-PT.wxl WixUI_ro-RO.wxl WixUI_ru-ru.wxl WixUI_sk-SK.wxl WixUI_sl-SI.wxl WixUI_sq-AL.wxl WixUI_sr-Latn-CS.wxl WixUI_sv-SE.wxl WixUI_th-TH.wxl WixUI_tr-TR.wxl WixUI_uk-UA.wxl WixUI_zh-CN.wxl WixUI_zh-HK.wxl WixUI_zh-TW.wxl |
Dialog Set
の各ファイルはDialogs
の各画面を表示する順番を規定しており、Localization File
は各ダイアログボックスに表示されるローカライズされた文面が格納されています。これらのファイルはコンパイルされ、C:\Program Files (x86)\WiX Toolset v3.11\bin\WixUIExtension.dll
として提供されています(執筆時点のパス)。改造が不要な場合はこれをそのまま使えば良いわけですが、例えばどれかのダイアログボックスをスキップさせたい場合はDialog Set
のファイルを自分のプロジェクトにコピーしてきて改造すれば可能です。また、画面デザインに手を入れたければ、Dialogs
のファイルを自分のプロジェクトにコピーしてきて改造し、Dialog Set
側でそのダイアログボックスを表示するように変更すれば可能です。文面を変えたければ、Localization File
のファイルに書式を合わせて、拡張子.wxl
のファイルを作成すれば良いのです。
ダイアログボックスをスキップする
WixUI_FeatureTree
Dialog SetのソースWixUI_FeatureTree.wxs
を以下に示します(説明に不要なコメント文は削除してあります)。
このファイルを自分のプロジェクトのフォルダにコピーして、適当なファイル名に変更します。Visual Studioで作業しているなら、プロジェクトに追加してやります。図中、(1)の部分で使用するダイアログボックスを定義し、(2)の部分で主に[次へ]ボタンや[戻る]ボタンを押した後に表示するダイアログボックスを定義しています。(2)の部分を読むと、新規インストール時(NOT Installedの時)にNext
ボタンの動作をたどっていくと、次のようなルートをたどるのがわかります。
WelcomeDlg
→LicenseAgreementDlg
→CustomizeDlg
→VerifyReadyDlg
ここで、LicenseAgreementDlg
をスキップしてみましょう。WelcomeDlg
でNext
を押したときCustomizeDlg
に移動すればよいので、(4)の部分をCustomizeDlg
に書き換えます。画面をスキップするための変更はこれだけですが、このファイルを改造して使う際には、WixUIExtension.dll
に入っているダイアログボックスのデザインを使用する必要があります。Id=WixUI_FeatureTree
のDialog Setもこの中に入っているため、改造用のファイルで同じIdを使えません。そこで、(3)のIdを変更してから改造していきます。変更後のファイルは下記のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="WixUI_Part21">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="FeatureTree" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1">Installed</Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg" Order="2">NOT Installed</Publish>
<Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="1">NOT Installed OR WixUI_InstallMode = "Change"</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3">Installed AND PATCH</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="CustomizeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Wix>
このDialog Setを使うよう、Product.wxs
も変更します。UIRefエレメントで上記のUIエレメントに指定したIdを指定してやるだけです。
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="59FEE1D2-A612-40B0-96B5-FDE465304B9B" Name="Part21_01" Language="1033" Version="1.0.0" Manufacturer="tohshima" UpgradeCode="05fd1b28-50a8-4d86-92fa-5adfe2fae0de">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<UIRef Id="WixUI_Part21"/>
<Feature Id="ProductFeature" Title="Part21_01" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Part21_01" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="cExe" Guid="{D5B5ADA3-AC19-4B5D-A5CB-7FBBB2548530}" >
<File Id="fExe" Source="C:\Windows\System32\calc.exe" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
これで、新規インストール時にLicenseAgreementDlg
がスキップされます。
-
Windows Installerには外部のプログラムにUI表示を任せる仕組みもあります。これを使って、インストールの進捗状況を外部のプログラムに表示されることもできます。 ↩
-
Windows SDKでインストーラーを作る場合も、SDKが用意したテンプレートを改造していくことになります。MSI形式のインストーラーがどれも似たようなUIを持つのも、インストーラー作成ツールがこのテンプレートを手本にしているからでしょう。
Microsoft Windows SDK for Windows 7 and .NET Framework 4
を使っているなら、C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\msitools
フォルダ以下にいくつかMSIが置いてあるので、興味があれば見てみてください。 ↩