はじめに
注意
今回の記事は前回の記事の続きになります。
用意しているコードはすべて前回の続きからとなりますのでご注意ください。
あらためて、はじめに
前回では、.NET5で作成したアプリケーションをWixSharp (Wix) を使用してインストーラにする、ということを実施しました。
しかしながら、.NET5はまだ広く一般ユーザに浸透しているとは言い難く、.NET5のランタイムをユーザにインストールしていただくということが必要になってくるかと思います。
Wixでは Bundle
という方法で、依存するランタイムなどを一緒にインストールさせることが可能となります。
本記事では、その Bundle
の使い方を紹介するとともに、 Bundle
で作成したインストーラを同時に日本語化するところまでを実施します。
あれ、でも日本語化って前回で。。。
前回までの記事をご覧になられていたそこのあなた、「日本語化はすでに前回実施したはずでは」と思われたはずです。
それはその通りですが、今回は「複数のインストーラを実行するインストーラを作成する」ということを実施することになりますので、ですから、別途日本語化作業が必要となるわけです。
サンプルコード
また、この記事で紹介しているコードは以下のリポジトリに配置しております。
実行環境
- VisualStudio2019
- Windows10Pro 20H2 (Build: 19042.867)
- .NET5 SDK 5.0.1
参考
本件を実施するにあたっていろいろと質問した経緯
みなさま、その節は本当にありがとうございました。この場を借りて御礼を申し上げます。。。
実装
ランタイムのバンドル
事前準備
今回も事前準備が必要です。
- バンドルさせたいインストーラのDL
- バンドルさせたいインストーラのDL元URLの確保
- バンドルさせたいインストーラからWix用のmetadataの抽出
- 実際にバンドル対象のインストーラからインストールを行い、レジストリがどうなるかを調べる
1. バンドルさせたいインストーラのDL
今回は .NET5 Desktop Runtime
のインストーラを、インストール時に実行させたい(=バンドルさせたい)ので、.NET5 Desktop Runtime
をDLします
特にこだわりがないのであれば、アーキテクチャは64bit版(=x64)で良いです
2. バンドルさせたいインストーラのDL元URLの確保
DL画面で、現在取得したインストーラのダウンロードURLを取得できますので、ここで取得しておきましょう
画面中央部の Direct link
となっている個所です
3. バンドルさせたいインストーラからWix用のmetadataの抽出
次に、metadataの抽出です
以下のコマンドを実行することで、Wix用のmetadataをXML形式で抽出することができます
注意: 以下、 heat
コマンドが出てきますが、こちらは Wix Toolset をインストールしておかないと使用することはできませんので、あらかじめインストールをお願い致します
PS> heat payload <バンドルしたいexeのバイナリのパス> -out .\remote.xml
-out
で指定したファイルにmetadataが出力されていますので、それを利用しましょう。
例えばですが、今回の場合は.NET5 Version5.0.5のWindows Desktop Runtimeを使用しましたが、このような形で出力されます
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<RemotePayload CertificatePublicKey="F49F9B33E25E33CCA0BFB15A62B7C29FFAB3880B" CertificateThumbprint="ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B" Description="Microsoft Windows Desktop Runtime - 5.0.5 (x64)" Hash="9CE1E77FE51E3F104D1DF7670F83F12B8ABF82F6" ProductName="Microsoft Windows Desktop Runtime - 5.0.5 (x64)" Size="54977944" Version="5.0.5.29917" />
</Fragment>
</Wix>
4. 実際にバンドル対象のインストーラからインストールを行い、レジストリがどうなるかを調べる
インストールをしましょう、まずはそこからです。
そして、レジストリエディタを見ましょう。
おおむね、.NET5の場合は以下のキーに存在しています。
コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost
レジストリがADの設定等で見られないと嘆いているそこのあなた!
Powershellを使うという手もあります
PS> Get-ChildItem -LiteralPath 'HKLM:\SOFTWARE\dotnet\Setup\InstalledVersions\x64' -Recurse
Powershellの場合、このように結果が出力されます
Hive: HKEY_LOCAL_MACHINE\SOFTWARE\dotnet\Setup\InstalledVersions\x64
Name Property
---- --------
sharedhost Version : 5.0.5
このVersion情報が後々必要となってきますので、ご注意ください
ランタイムのバンドルのコード実装
以下の通りです、順を追って説明します
// :
// これより上は前回の内容となりますのでそちらをご覧ください
// :
// インストール先を Program Files (x86) から Program Files に変更する
project.Platform = Platform.x64;
// インストール時に管理者権限を要求
project.InstallPrivileges = InstallPrivileges.elevated;
// インストール先をPC全体に変更
project.InstallScope = InstallScope.perMachine;
var projectMsi = project.BuildMsi();
var bootstrapper = new Bundle(
"ウィンドウズサービステスト_バンドルインストーラ",
new ExePackage()
{
Id = "DotNet5DesktopRuntime",
Name = "dotnet5-windowsdesktop-runtime-5.0-win-x64.exe",
Vital = true,
Permanent = false,
DownloadUrl = @"https://download.visualstudio.microsoft.com/download/pr/c1ef0b3f-9663-4fc5-85eb-4a9cadacdb87/52b890f91e6bd4350d29d2482038df1c/windowsdesktop-runtime-5.0.5-win-x64.exe
",
InstallCommand = "/install /quiet",
RepairCommand = "/repair /quiet",
UninstallCommand = "/uninstall /quiet",
LogPathVariable = "dotnet5desktopruntime.log",
Compressed = true,
// RemotePayloadは以下のコマンドで取得可能
// heat payload <バンドルしたいexeのバイナリのパス> -out .\remote.xml
RemotePayloads = new[]
{
new RemotePayload()
{
ProductName = "Microsoft Windows Desktop Runtime - 5.0.5 (x64)",
Description = "Microsoft Windows Desktop Runtime - 5.0.5 (x64)",
Hash="9CE1E77FE51E3F104D1DF7670F83F12B8ABF82F6",
Size = 54977944,
Version = "5.0.5.29917".ToRawVersion(),
CertificatePublicKey = "F49F9B33E25E33CCA0BFB15A62B7C29FFAB3880B",
CertificateThumbprint = "ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B"
}
},
new MsiPackage(projectMsi)
}
);
// ランタイムバンドルインストーラのバージョン
bootstrapper.Version = new Version("1.0.0.0");
// ランタイムバンドルインストーラのアップグレードコード (変更厳禁)
bootstrapper.UpgradeCode = new Guid("XXXXX");
// ランタイムバンドルインストーラのアプリケーションスタイルの定義
bootstrapper.Application = new LicenseBootstrapperApplication();
// 表示する利用規約の指定
bootstrapper.Application.LicensePath = @".\Eula.rtf";
// インストール時のOption非表示
bootstrapper.Application.SuppressOptionsUI = true;
// アンインストール時の修復を非表示
bootstrapper.Application.SuppressRepair = true;
// 一次領域を使用するか
bootstrapper.PreserveTempFiles = true;
// Wixの必須パラメータの定義?は行わない
bootstrapper.SuppressWixMbaPrereqVars = false;
// インストーラ名の定義
bootstrapper.OutFileName = "MyAwesomeSetup";
// ランタイムバンドルインストーラの作成
bootstrapper.Build();
var projectMsi = project.BuildMsi();
前回作成した.msiのインストーラのパスを projectMsi
で受けます
後の Bundle
のインスタンス作成時に指定します
var bootstrapper = new Bundle("ウィンドウズサービステスト_バンドルインストーラ", ...
バンドルするインストーラのバンドルインスタンスを作成します
第一引数ではインストーラの名前(多くは製品名でしょう)を入力し、
第二引数以降では、バンドルするインストーラの情報を入力します
第二引数以降で、必ずそれより前に作成したアプリ単体のインストーラを含めることを忘れないように注意しましょう
Id = "DotNet5DesktopRuntime"
バンドルのIDです。たぶん、なんでもいいです。たぶん。わかりやすく名付けしておきましょう。
Name = "dotnet5-windowsdesktop-runtime-5.0-win-x64.exe"
バンドルの名前です。たぶん、なんでもいいです。たぶん。わかりやすく名付けしておきましょう。
Vital = true,
これちょっと重要です。
true
で、「このバンドルのインストールが失敗した場合、後続のインストーラも失敗する」という設定になります
失敗させたくない場合は false
にしましょう
Permanent = false
インストール元のパッケージのアンインストール時に、一緒にアンインストールさせるかどうかを決定します
false
で一緒にアンインストール させない です
DownloadUrl = "https://download.visualstudio.microsoft.com/download/pr/c1ef0b3f-9663-4fc5-85eb-4a9cadacdb87/52b890f91e6bd4350d29d2482038df1c/windowsdesktop-runtime-5.0.5-win-x64.exe"
これも重要ですが、ここで指定する値はすでに取得しています
ここでは、事前準備で取得したパッケージのDL元のURLを指定すればそれでよいです
InstallCommand
/ RepairCommand
/ UninstallCommand
それぞれインストール時、修復時、アンインストール時に実行するコマンドを指定することができます
多くのインストーラは /install
/uninstall
のようなコマンドライン引数をサポートしていますので、それを指定してやればよいです
なお、.NET5 WindowsDesktopRuntimeの場合、 /quiet
でインストール時に .NET5 WindowsRuntimeDesktop のインストーラ画面を表示させない、というオプションを持っています
LogPathVariable = "dotnet5desktopruntime.log",
このインストーラ(.NET5Runtimeのインストーラ)がミスった時にログを出すことができますが、そのログのファイル名を指定できます
Compressed = true
圧縮オプションです
RemotePayloads = new[]
こいつがめちゃくちゃ重要です
ここでは以下のように設定していますが、ここで指定する内容は 事前準備の「3. バンドルさせたいインストーラからWix用のmetadataの抽出」で取得したmetadataです
取得したXMLをよく読んで、しっかり指定してあげましょう
new RemotePayload()
{
ProductName = "Microsoft Windows Desktop Runtime - 5.0.5 (x64)",
Description = "Microsoft Windows Desktop Runtime - 5.0.5 (x64)",
Hash="9CE1E77FE51E3F104D1DF7670F83F12B8ABF82F6",
Size = 54977944,
Version = "5.0.5.29917".ToRawVersion(),
CertificatePublicKey = "F49F9B33E25E33CCA0BFB15A62B7C29FFAB3880B",
CertificateThumbprint = "ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B"
}
作成したインストーラを実行してみる
このようにインストーラが表示されていればバッチリです!
日本語化
いよいよ日本語化ですが、残念ながらここでも事前準備は必要です
仕事は準備7割とかって言いますものね、仕方ありませんので根気強くやっていきましょう
事前準備
以下のプロセスが必要です
- インストーラを日本語にするための
.wxl
ファイルの作成 -
.wxl
をVisualStudioで管理するようにする
面倒ですが、やっていきましょう
1. インストーラを日本語にするための .wxl
ファイルの作成
そもそも
.wxl
ファイルとは、ローカライゼーション対応のためのファイルで、XML形式で書かれます。
日本語化に際して、必ずこれが必要となります
用意
.wxl
ファイルの作成とはいいましたが、以下をそのまま持ってくるのもきっとありでしょう。
少なくとも私は、どのような値を定義すればよいのかがわかりませんでしたので。。。
(こういうところをWiXの公式で救ってくれると非常にありがたいんですけどね。。。)
これを利用する際に一つ注意点なのですが、一部タイトル部分がこのままだときちんと表示されないので、次のように変えることをおススメします
<String Id="Title">[WixBundleName]</String>
<String Id="SubTitle">[WixBundleName]</String>
2. .wxl
をVisualStudioで管理するようにする
このようにしてください
今回用意した .wxl
ファイルは thm.wxl
としてプロジェクトの直下に保存しています
そのプロパティとして、以下を定義しています
- ビルドアクション: コンテンツ
- 出力ディレクトリにコピー: 常にコピーする
実装
ようやく実装ですが、書く内容は以下のみで大丈夫です
// ランタイムバンドルインストーラのバージョン
bootstrapper.Version = new Version("1.0.0.0");
// ランタイムバンドルインストーラのアップグレードコード (変更厳禁)
bootstrapper.UpgradeCode = new Guid("bf3b1aeb-12c5-4401-ad23-6a49f905bd55");
// ランタイムバンドルインストーラのアプリケーションスタイルの定義
bootstrapper.Application = new LicenseBootstrapperApplication();
bootstrapper.Application.LicensePath = @".\Eula.rtf";
+// ローカライゼーションファイルの指定
+bootstrapper.Application.LocalizationFile = "thm.wxl";
// インストール時のOption非表示
bootstrapper.Application.SuppressOptionsUI = true;
// アンインストール時の修復を非表示
bootstrapper.Application.SuppressRepair = true;
// 一次領域を使用するか
bootstrapper.PreserveTempFiles = true;
// Wixの必須パラメータの定義?は行わない
bootstrapper.SuppressWixMbaPrereqVars = false;
// インストーラ名の定義
bootstrapper.OutFileName = "ウィンドウズサービステスト_バンドルインストーラ";
// ランタイムバンドルインストーラの作成
bootstrapper.Build();
実行
このように日本語で表示されていれば、それでOKです
問題点
今回紹介した日本語化対応は、「インストーラをマルチロケール(i18n的なもの)に対応することが、そのままだとできない」というところが問題点となるかと思います。
つまり、今回紹介した方法とは、あくまで、「日本語のインストーラしか要らないから、日本語化されたインストーラをWixSharpで作りたい」という時に使用できる対応方法になります。
お気を付けください。
インストーラがうまく動かない!でもエラーが表示されない!そんな時は……
エクスプローラで %Temp%
を参照してみてください。何かしらログが吐かれていると思います。このログを基に、調査することも可能です。
おわりに
このようにして、インストーラに.NET5のランタイムはバンドルできますし、日本語化もばっちり対応できるかと思います
あぁ、次はインストールコンディションだ。。。
同じ開発者の助けになる記事になることを望みます。
また、何か誤っている個所がありましたらご指摘ください。
ここまで読んでくださり、ありがとうございました。