3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WixSharpで作成するインストーラに.NET5 Runtimeをバンドルする方法と、バンドルインストーラを日本語化する方法

Last updated at Posted at 2021-04-25

はじめに

注意

今回の記事は前回の記事の続きになります。
用意しているコードはすべて前回の続きからとなりますのでご注意ください。

あらためて、はじめに

前回では、.NET5で作成したアプリケーションをWixSharp (Wix) を使用してインストーラにする、ということを実施しました。
しかしながら、.NET5はまだ広く一般ユーザに浸透しているとは言い難く、.NET5のランタイムをユーザにインストールしていただくということが必要になってくるかと思います。
Wixでは Bundle という方法で、依存するランタイムなどを一緒にインストールさせることが可能となります。
本記事では、その Bundle の使い方を紹介するとともに、 Bundle で作成したインストーラを同時に日本語化するところまでを実施します。

あれ、でも日本語化って前回で。。。

前回までの記事をご覧になられていたそこのあなた、「日本語化はすでに前回実施したはずでは」と思われたはずです。

それはその通りですが、今回は「複数のインストーラを実行するインストーラを作成する」ということを実施することになりますので、ですから、別途日本語化作業が必要となるわけです。

サンプルコード

また、この記事で紹介しているコードは以下のリポジトリに配置しております。

実行環境

  • VisualStudio2019
  • Windows10Pro 20H2 (Build: 19042.867)
  • .NET5 SDK 5.0.1

参考

本件を実施するにあたっていろいろと質問した経緯

みなさま、その節は本当にありがとうございました。この場を借りて御礼を申し上げます。。。

実装

ランタイムのバンドル

事前準備

今回も事前準備が必要です。

  1. バンドルさせたいインストーラのDL
  2. バンドルさせたいインストーラのDL元URLの確保
  3. バンドルさせたいインストーラからWix用のmetadataの抽出
  4. 実際にバンドル対象のインストーラからインストールを行い、レジストリがどうなるかを調べる

1. バンドルさせたいインストーラのDL

今回は .NET5 Desktop Runtime のインストーラを、インストール時に実行させたい(=バンドルさせたい)ので、.NET5 Desktop Runtime をDLします

特にこだわりがないのであれば、アーキテクチャは64bit版(=x64)で良いです

image.png

2. バンドルさせたいインストーラのDL元URLの確保

DL画面で、現在取得したインストーラのダウンロードURLを取得できますので、ここで取得しておきましょう

画面中央部の Direct link となっている個所です

image.png

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"
            }

作成したインストーラを実行してみる

このようにインストーラが表示されていればバッチリです!

image.png

日本語化

いよいよ日本語化ですが、残念ながらここでも事前準備は必要です

仕事は準備7割とかって言いますものね、仕方ありませんので根気強くやっていきましょう

事前準備

以下のプロセスが必要です

  1. インストーラを日本語にするための .wxl ファイルの作成
  2. .wxl をVisualStudioで管理するようにする

面倒ですが、やっていきましょう

1. インストーラを日本語にするための .wxl ファイルの作成

そもそも

.wxl ファイルとは、ローカライゼーション対応のためのファイルで、XML形式で書かれます。
日本語化に際して、必ずこれが必要となります

用意

.wxl ファイルの作成とはいいましたが、以下をそのまま持ってくるのもきっとありでしょう。
少なくとも私は、どのような値を定義すればよいのかがわかりませんでしたので。。。
(こういうところをWiXの公式で救ってくれると非常にありがたいんですけどね。。。)

これを利用する際に一つ注意点なのですが、一部タイトル部分がこのままだときちんと表示されないので、次のように変えることをおススメします

  <String Id="Title">[WixBundleName]</String>
  <String Id="SubTitle">[WixBundleName]</String>

2. .wxl をVisualStudioで管理するようにする

このようにしてください

今回用意した .wxl ファイルは thm.wxl としてプロジェクトの直下に保存しています
そのプロパティとして、以下を定義しています

  • ビルドアクション: コンテンツ
  • 出力ディレクトリにコピー: 常にコピーする

image.png

実装

ようやく実装ですが、書く内容は以下のみで大丈夫です

// ランタイムバンドルインストーラのバージョン
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です

image.png

問題点

今回紹介した日本語化対応は、「インストーラをマルチロケール(i18n的なもの)に対応することが、そのままだとできない」というところが問題点となるかと思います。

つまり、今回紹介した方法とは、あくまで、「日本語のインストーラしか要らないから、日本語化されたインストーラをWixSharpで作りたい」という時に使用できる対応方法になります。

お気を付けください。

インストーラがうまく動かない!でもエラーが表示されない!そんな時は……

エクスプローラで %Temp% を参照してみてください。何かしらログが吐かれていると思います。このログを基に、調査することも可能です。

おわりに

このようにして、インストーラに.NET5のランタイムはバンドルできますし、日本語化もばっちり対応できるかと思います

あぁ、次はインストールコンディションだ。。。

同じ開発者の助けになる記事になることを望みます。

また、何か誤っている個所がありましたらご指摘ください。
ここまで読んでくださり、ありがとうございました。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?