WinUI 3 で Native AOT が簡単になっていた
はじめに
速いと話題の Native AOT(以降「AOT」)ですが、これまでは「何か対応するのが面倒くさそう」という印象でした。
しかし、.NET 9 時代になってそこそこ簡単に AOT できるようになっていたので、手順を整理しておきます。
なお、「そもそも AOT とは」についてはこちらの記事が分かりやすいです。
開発環境の確認
AOT するには C# 開発用のワークロードに加えて「C++ によるデスクトップ開発」が必要です。
Visual Studio Installer でワークロードを確認し、入れていない場合は入れます。
また、Visual Studio の[拡張機能 → 拡張機能の管理]メニューで、WinUI 3 の開発を便利にする「Template Studio for WinUI」をインストールします。
プロジェクト作成
作成
Visual Studio の新しいプロジェクトの作成で「WinUI の Template Studio」テンプレートを選択します。
プロジェクトの種類はシンプルに「空白」にします。
機能の「内蔵」はオフのままでもオンにしても(自己完結型)、どちらでも大丈夫です。
設定
プロジェクト作成後、ツールバーまたは[ビルド → 構成マネージャー]メニューで、アクティブソリューションプラットフォームを「Release」「x64」にします。
[プロジェクト → ProjectName のプロパティ]メニューでメインプロジェクト(Core の付いていないほう)のプロパティを開き、
項目 | 値 |
---|---|
アプリケーション → 全般 → ターゲットフレームワーク | .NET 9.0 |
ビルド → 公開 → ネイティブ AOT の公開 | オン |
にし(自動的にトリミングもオンになります)、プロジェクトを保存します。
同様に、Core の付いているほうのプロジェクトのプロパティも
項目 | 値 |
---|---|
アプリケーション → 全般 → ターゲットフレームワーク | .NET 9.0 |
にします。
ソリューションエクスプローラーでメインプロジェクト(Core の付いていないほう)をダブルクリックし、プロジェクトファイルを XML エディタで開きます。
<PropertyGroup>
に 1 行追加します。これはビルドエラー対策ですが、詳細についてはこちらの記事をご覧ください。
<PropertyGroup>
...(略)...
<UseRidGraph>true</UseRidGraph>
...(略)...
</PropertyGroup>
[ツール → NuGet パッケージマネージャー → ソリューションの NuGet パッケージの管理]で、インストール済のすべてのパッケージを更新して最新化します。
ビルド
AOT は通常のビルドでは有効にならず、発行時のみ有効になります。
手軽な発行方法としては、ソリューションエクスプローラーでプロジェクトの右クリックメニューからの「発行」ですが、手元の環境では「発行」で作成した exe をダブルクリックしても起動しなかったため(恐らくシステムに登録できないため)、多少手間はかかりますがパッケージ化します。
証明書の作成
パッケージ化するためには証明書が必要なので、オレオレ証明書を作成します。
ソリューションエクスプローラーで Package.appxmanifest
をダブルクリックし、「パッケージ化」タブを開きます。
「証明書の選択」ボタンをクリックすると証明書の選択ウィンドウが表示されるので、「作成」ボタンをクリックします。
自己署名入りのテスト証明書の作成ウィンドウで適当に内容を入力すると証明書が作成されます。
自己署名入りのテスト証明書の作成について、詳しくはこちらの記事をご覧ください。
パッケージ化
ソユーションエクスプローラーでメインプロジェクトを右クリックし、[パッケージ化して公開する → アプリパッケージの作成]メニューをクリックします。
配付方法を「サイドローディング」にして次に進みます。
署名方法の選択では、先ほど作成した証明書が自動的に選択されているので、そのまま次に進みます。
パッケージの選択と構成では、アーキテクチャは x64 のみで良いので他のチェックは外します。
更新設定の構成では、インストーラーの場所を適当に入力します。
(例)http://example.com/
作成ボタンをクリックするとパッケージが作成され、出力場所のリンクをクリックするとパッケージの場所がエクスプローラーで開かれます。
実行
インストール
作成されたフォルダー一式を他の PC にコピーし、フォルダー内にある Install.ps1
を Windows PowerShell にドラッグ&ドロップして実行すると、作成したアプリがインストールされます。
なお、PowerShell でスクリプトを実行可能にするための設定方法はこちらの記事にあります。
起動
インストールするとスタートメニューに登録されるので、スタートメニューから起動します。
AOT の確認
ファイルの確認
アプリ起動中にタスクマネージャーを起動し、[アプリ右クリック → ファイルの場所を開く]で exe のフォルダーがエクスプローラーで開かれます。
AOT ではない場合、プロジェクトと同名の exe と dll の 2 つのファイルがありますが(プロジェクトが Test
なら Test.exe
と Test.dll
)、AOT の場合は exe のみとなり、プロジェクトと同名の dll はありません(他の dll はあります)。
ファイルサイズ
AOT を有効にすると自動的にトリミング(不要なメソッド等をバイナリから除去)も有効になるため、ファイルサイズは AOT しない場合よりも小さくなる傾向にあります。
トリミングの度合いによってもファイルサイズは変わり、トリミングの度合いはプロジェクトファイルを XML で編集し、<TrimMode>
により指定できます。
<PropertyGroup>
...(略)...
<TrimMode>full</TrimMode>
...(略)...
</PropertyGroup>
デフォルトでは <TrimMode>
は full
で、最大限トリミングします。partial
にするとほんのりとトリミングします。
ファイルサイズは自己完結型にするかによっても変わります。プロジェクト作成時に選べますが、後から変更するには、プロジェクトファイルを XML で編集し、<WindowsAppSDKSelfContained>
により指定します。
<PropertyGroup>
...(略)...
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
...(略)...
</PropertyGroup>
true
(自己完結型)か false
(フレームワーク依存)で指定します。
フレームワーク依存の場合のファイルサイズは以下のようになりました。
AOT | ファイルサイズ [MB] |
---|---|
AOT 無効 | 158.0 |
AOT TrimMode partial | 24.1 |
AOT TrimMode full | 10.0 |
自己完結型のファイルサイズは以下のようになりました。
AOT | ファイルサイズ [MB] |
---|---|
AOT 無効 | 212.0 |
AOT TrimMode partial | 77.1 |
AOT TrimMode full | 62.9 |
詳細はこちらをご覧ください。
速度
体感ですが、AOT していない場合は初回起動時にワンテンポ遅れてウィンドウが表示されるのに対し、AOT を有効にすると、早めにウィンドウが表示されるように感じました。
トラブル対策
そこそこ簡単に AOT できるようになったものの、まだまだ整備されてない部分もあり、いろいろなトラブルにも遭遇したので、その対策を書いておきます。
APPX1101 エラー
ビルド時に APPX1101 エラーが発生することがあります。
- プロジェクト作成時、設定を最後までやってからビルドしないとエラーになるので、最後まで設定します。
- 上記に含まれますが、パッケージが古いとエラーになるので、最新化します。
- いったん「ソリューションのクリーン」をします。
- クリーンでもダメな場合は、メインプロジェクトと Core プロジェクトの
bin
obj
フォルダーをフォルダーごと削除します。
NETSDK1083 エラー
ビルド時に NETSDK1083 エラーが発生することがあります。
- プロジェクト作成時、設定の
<UseRidGraph>
を忘れていますので、設定します。
パッケージ化メニューが見当たらない
ソリューションエクスプローラーでメインプロジェクトを右クリックした時に、「パッケージ化して公開する」が表示されない場合があります。
普通のビルドをしたり、Visual Studio を再起動したりしていると表示されます。
WinForms や WPF で AOT できない
今回は WinUI 3 アプリを AOT にしました。
残念ながら今のところ、WinForms や WPF アプリではトリミングができないため、トリミング必須の AOT もできません(頑張ればトリミングできる回避策もあるようです)。
いずれすんなりと AOT できるようになることを期待したいところです。
AOT 自身の制約
例えば一部(ほとんど?)のリフレクションは AOT では使えないなど、AOT にすることによりプログラミングに制約が発生します。
今回のようなテンプレートアプリなら簡単ですが、実際のアプリ開発ではかなりの困難が予想されます。
ソースジェネレーターを使用したり、AOT 対応のライブラリを使用したりすることにより回避可能になりつつありますが、まだまだの部分もあるようです。
時と共に回避策が発展していくことを期待したいところです。
トラブル対策(解決済)
今後は発生しないと思われるトラブルです。
備忘として残しておきます。
Microsoft Store にアップロードできない
Template Studio for WinUI ではなく、標準の WinUI テンプレート(空白のアプリ、Windows アプリケーションパッケージプロジェクトでパッケージ化(デスクトップの WinUI 3))でアプリを作成した場合、パッケージ化で作成される .msixupload
を Microsoft Store のパートナーセンターにアップロードするとエラーになります。
サポートされていないバージョンのファイル makepri.exe (10.0.26100.1742) を使用しています。
手動でパッケージを作成することで回避できるようです。
Windows 10 にインストールできないことがある
これは AOT に関わらずですが、パッケージを Windows 10 にインストールするために Install.ps1
を実行すると
Add-AppxPackage : 次の HRESULT で展開に失敗しました: 0x80073CF9, インストールに失敗しました。ソフトウェアの製造元に問い合わせてください。 (HRESULT からの例外:0x80073CF9)
というエラーになってインストールできないことがありました。
サイドローディングの場合だけではなく、Microsoft Store 経由でも入手ボタンがグレーアウトしてインストールできませんでした。
Windows App SDK 1.5 系では発生しなかったので、1.6 系の不具合なのかもしれません。
問題なくインストールできる Windows 10 環境もありました。
サンプルプログラム
こちらの記事に AOT で動作するプログラムがありますのでどうぞ。
確認環境
項目 | 環境 |
---|---|
OS | Windows 11 Pro 23H2 / Windows 10 Pro 22H2 |
Visual Studio | 2022 17.12.0 |
.NET | 9.0 |
Template Studio for WinUI | 5.5 |
WinUIEx | 2.5.0 |
Windows App SDK | 1.6.241114003 (1.6.3) |
参考リンク
- Native AOT deployment
- 【C#】コンパイルが必要な言語はダメらしいので「NativeAOT」について紹介
- .NET 8 で WinUI 3 アプリをビルドする(NETSDK1083 対策)
- WinUI 3 アプリの msixbundle を作成する
- PowerShellスクリプトを実行できるように設定する
- AOT ファイルサイズ比較
- Partner Center reporting a bug for latest version of BuildTools
- 既知のトリミングの非互換性
- Native AOT で COM を使ってみた
主な改訂履歴
- 2024/11/20 初版。
- 2024/11/21 インストールを更新。
- 2024/11/22 証明書の作成に追記。
- 2024/11/25 Windows 10 にインストールできないことがあるを更新。
- 2024/12/02 設定を更新。
- 2024/12/03 サンプルプログラムを記載、トラブル対策を更新。
Discussion