はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

.NET(旧名称.NET Core)アプリの配布方法について(勘違いしていたので)

.NET 5以降のフレームワークWindowsアプリ(以下、.NET Coreアプリ)を作成したとき、配布した実行可能ファイルが.NET Frameworkのときとは異なっている点を最近まできちんと把握していなかったので、忘備録代わりに投稿します。

.NET Coreアプリの2つの展開

.NET Coreアプリを配布する形式は2つの配置モード(展開形式)があります。
例として、hogehogeというアプリ名のアプリを配布する場合について考えてみましょう。

フレームワーク依存

フレームワークに依存するという名称から、配布先のフレームワークx86かx64かなど配布先の環境を意識しないといけないように思えますが、そうではありません。

このファイル形式の良い点は2つ

  1. 配布ファイルはx86/x64の区別がない(1つだけ例外あり)
  2. 配布するファイルに.NETランタイムは入らないのでコンパクト(配布ファイルの例:66ファイル、合計62MB)
Any CPUでビルドしたものを配布できる

配布先にあるフレームワークに動作モードが依存するので、展開形式ではx86かx64かを意識しないでビルド、つまり、Any CPUでビルドすることができます。

配布先での実行はdll名指定で

hogehogeというアプリ名の場合、配布物の中では、hogehoge.dllがアプリファイルとなりますので、

dotnet hogehoge.dll

のようにして実行します。インストーラーの中で、アプリショートカットを作成して、このコマンドを実行するように設定するなどの工夫が必要です。

実行可能ファイル

hogehoge.dll以外にもhogehoge.exeというファイルも配布されますが、配布先でのhogehoge.exeの実行には注意が必要です。
dotnet hogehoge.dll」での実行は配布先がx86環境でもx64環境でも(なんならWindows環境以外でも場合によっては)実行ができます。
しかし「hogehoge.exe」での実行は、例えば、開発環境がx64だった場合、hogehoge.exeは64bitアプリとして作成されるので実行環境がx86環境の環境に配布しても実行できません
また、開発環境がx86だった場合、hogehoge.exeは86bitアプリとして作成されるのでx64環境に配布してもx64アプリではなくx86アプリとして動作しようとするので、x86の.NET6ランタイムがないと実行できません
この赤字の部分が勘違いしていて、「なんでx86環境で動かないんだ~」と1日悩んでいました。
x64環境でビルドして、フレームワーク依存で配布した場合、x86環境での実行は「dotnet hogehoge.dll」一択です!

自己完結

配置モードとして「自己完結」を選択すると、ターゲットランタイムも含めた形で実行に必要なファイルがすべて含んでファイルが生成されます。

このファイル形式の良い点は、次の点です。

  1. 配布先の環境で、を事前にインストールする必要がない(配布ファイルの例:350ファイル、合計214MB)

その代わり、Any CPUビルド指定していたとしても、ターゲットランタイムとして「win-x64」と指定するので、作成されたファイルは、DLLも含め、Windows x64環境に依存したものになります。
もし、x86とx64の両方に配布する予定があるのであれば、x86用自己完結インストーラーとx64用自己完結インストーラーの2つのmsiファイルを作成する必要があります。

Visual Studio Installer Projectでのmsiファイル作成

Visual Studio 2022と最新のVisual Studio Installer Project Templateを使えば、.NET Coreアプリもmsiファイルとしてインストーラーファイルを作成することができます。

配置モードが「自己完結」の時のインストーラープロジェクト

配置モードを「自己完結」としてVisual Studioから「発行」したものをVisual Studio Installer Projects 拡張機能を使ってmsiファイルを作る場合は次のような手順になります。

Setupプロジェクトの新規作成

Visual Studio Installer Projects 拡張機能をインストールしておくと、新規プロジェクトタイプして「Setup」が選択できます。

インストールターゲットの指定

インストーラープロジェクトが新規作成されたら、プロジェクトのTargetPlatformプロパティを発行時に選択したプラットフォームに合わせます。今回は「win-x64」としたので、「x64」を選びます。

「項目の公開」の追加

インストーラープロジェクトが新規作成されたら、プロジェクトを右クリックして[プロジェクト出力]を選択して、「項目の公開」をプロジェクトに追加します。

PublishProfilePathの設定

「項目の公開」がプロジェクトに追加されたら、そのPublishProfilePathプロパティに「発行」で作成ししたプロファイルファイルを指定します。

もちろん、この発行プロファイルの配置モードは「自己完結」にしておきます。
これにより、発行プロファイルに基づいたビルドが行われて、そこの出力を使ってmsiファイルが作成されます。

ビルドを開始しました...

            • Starting pre-build validation for project 'HogehogeTrialSetupCore' ------
            • Pre-build validation for project 'HogehogeTrialSetupCore' completed ------

1>------ ビルド開始: プロジェクト: HogehogeTrialSetupCore, 構成: Release ------
Building file 'C:\User\Project\dotNET\HogehogeTrialSetupCore\Trial\TrialSetup.msi'...
Packaging file 'System.Windows.Forms.Design.resources.dll'...
:
(中略)
:
Packaging file 'System.Net.Http.Json.dll'...
========== ビルド: 成功 1、失敗 0、最新の状態 1、スキップ 0 ==========
=========== 経過時間 01:19.271 ==========

配置モードが「フレームワーク依存」の時のインストーラープロジェクト

配置モードを「フレームワーク依存」としてVisual Studioから「発行」したものをVisual Studio Installer Projects 拡張機能を使ってmsiファイルを作る場合は次のような手順になります。

Setupプロジェクトの新規作成

Visual Studio Installer Projects 拡張機能をインストールしておくと、新規プロジェクトタイプして「Setup」が選択できます。

インストールターゲットの指定

インストーラープロジェクトが新規作成されたら、プロジェクトのTargetPlatformプロパティを「x86」とします。
こうすることで、x64環境でもx86環境でも動作するmsiファイルが作成できます。
なお、ここでx86と指定しても、インストールされるアプリ自体がx86アプリになるわけではありません。

「項目の公開」の追加

インストーラープロジェクトが新規作成されたら、プロジェクトを右クリックして[プロジェクト出力]を選択して、「項目の公開」をプロジェクトに追加します。

PublishProfilePathの設定

「項目の公開」がプロジェクトに追加されたら、そのPublishProfilePathプロパティに「発行」で作成ししたプロファイルファイルを指定します。

もちろん、この発行プロファイルの配置モードは「フレームワーク依存」にしておきます。
これにより、発行プロファイルに基づいたビルドが行われて、そこの出力を使ってmsiファイルが作成されます。

インストールプロセスの中でランタイムをインストール(前提条件の追加)

フレームワーク依存の場合、.NETランタイムが事前にインストールされていることが必要となりますので、インストーラーの実行プロセスの中で.NETランタイムもインストールするように設定します。
ソリューションエクスプローラーでプロジェクトを右クリックしてプロパティを表示します。
[Prerequisites]ボタンをクリックします。

必要なランタイムを指定します。

ランタイムのチェックだけでインストールは事前に実施

インストーラーの中でランタイムをインストールしないときは、前提条件は追加しないようにします。

配布先でのインストール結果の確認

配置モードが「自己完結」の時のインストール結果


アプリフォルダに.NETデスクトップランタイムに含まれるファイルもインストールされて、ファイル数350個がアプリフォルダに展開されます。

配置モードが「フレームワーク依存」の時のインストール結果


アプリフォルダに.NETデスクトップランタイムのファイルはインストールされないので、ファイル数66個となります。