はじめに
.NET 8.0+Native AOTでWindowsコンソールアプリを作成する方法です。
普段は .NET Framework 4.8.xを使用していますが .NET 8.0+Native AOTを使えば簡単にJIT
不要のコンソールアプリが作成できます。手元の環境はWindows10 x64です。
Native AOT(Ahead-Of-Time)について
Native AOT deployment overview - .NET | Microsoft Learn
Publishing your app as Native AOT produces an app that's self-contained and that has been ahead-of-time (AOT) compiled to native code.
アプリをNative AOTとして公開するとネイティブ コードに事前コンパイルされるため.NET ランタイムのない環境でも実行することができます。
.NET Framework 4.8.xはWindows10/11に既定でインストールされており、追加でランタイムを入れる必要がない一方で、起動が遅いという欠点があります。AOTであればその欠点を補うことができます。
開発環境
Native AOT開発では「C++によるデスクトップ開発」を含むVisual Studio 2022が必要になります。
C++によるデスクトップ開発
Visual Studio Installerで「C++によるデスクトップ開発」にチェックを入れます。コンソールアプリであればVS Code + C#拡張機能を使用したコーディングのほうが軽量でよいと思いますがVisual Studioでコーディングする場合は、「.NET デスクトップ開発」にもチェックを入れます。
.NET SDK
個別のコンポーネントで .NET SDKにチェックを入れます。SDKにチェックを入れると.NET8.0ランタイムも同時にインストールされます。上記で「.NET デスクトップ開発」にもチェックを入れた場合はその時点でチェックが入りますので本操作は不要です。
アプリの作成
Native AOT開発のページに"GitHubにサンプルがあります"と書かれているのでそちらを参考にします。
- プロジェクトの作成
コマンド プロンプトで以下のコマンドを実行することでHelloWorldというフォルダが作成され、Program.cs
とプロジェクトファイルHelloWorld.csproj
が作成されます。既定では最上位レベルのステートメントが有効です。無効にする場合は、dotnet new console -o HelloWorld --aot
dotnet new console -o HelloWorld --use-program-main --aot
- コードの記述
Program.cs
にコードを記述します。デフォルトではHello, World!
と表示するコードになっています。// See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!");
- 公開
HelloWorld
フォルダをコマンド プロンプトで開いて、以下のコマンドを実行すると、.\bin\Release\net8.0\win-x64\publish
内にHelloWorld.exe
が作成されます。dotnet publish
- 実行
コマンドプロンプト上でHelloWorld.exe
を実行するとHello, World!
と表示されます。
補足
.NET 8.0+Native AOTでの開発にあたり
普段は .NET Framework 4.8.xを使用しているため、.NET 8.0+Native AOTで開発する上での覚え書きを記載しておきます。
-
.NET Framework 4.8.xではなく .NET 8.0を使用することでより新しいバージョンのC#で開発することができます。C#のバージョンについてはC# 言語の既定のバージョンとC# の歴史を参照。C#については C# 言語リファレンスや概要 - A tour of C#を参照。
-
引数を参照する場合は
args
変数を使用します。args[0]
は自身のパスではなく引数1個目です。 -
以下の using ディレクティブが自動的に追加されます。
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
無効にする場合は
*csproj
ファイル(上記の例ではHelloWorld.csproj
)を開いて<ImplicitUsings>enable</ImplicitUsings>
の箇所を<ImplicitUsings>disable</ImplicitUsings>
にします。 -
自身のパスを取得するために
System.Reflection.Assembly.GetExecutingAssembly().Location
を使うとエラーになります。//自身のパスを取得 string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;//エラー string appPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;//代替例1 string appPath = Path.GetFullPath(Environment.GetCommandLineArgs()[0]);//代替例2。コマンドラインで使用する場合、拡張子をつけないで呼び出すとここでも拡張子なしとなる。 //自身のあるフォルダ string appFolder = System.AppContext.BaseDirectory;
-
起動時にコマンドプロンプトを出す必要がない/出したくない場合は
*csproj
ファイルのOutputType
をExe
からWinExe
に変更します。<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <PublishAot>true</PublishAot> <InvariantGlobalization>true</InvariantGlobalization> </PropertyGroup> </Project>
例えば、起動時に自身のパスを表示するだけのプログラムは、
Program.csusing System.Runtime.InteropServices; [DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int MessageBoxW(nint hWnd, [MarshalAs(UnmanagedType.LPWStr)] string lpText, [MarshalAs(UnmanagedType.LPWStr)] string lpCaption, uint uType); string appPath = Path.GetFullPath(Environment.GetCommandLineArgs()[0]); MessageBoxW(nint.Zero, appPath, "MyPath", 0);
Visual Studio 2022でコーディング
環境設定で「.NET デスクトップ開発」にもチェックを入れVisual Studioでコーディングする場合は、
- Visual Studio 2022を起動し、「新しいプロジェクトの作成(N)」を押します。
- 「コンソール アプリ」を選んで次へ。
- プロジェクトの名前と保存場所を設定し次へ。
- フレームワークとして「.NET 8.0」を選択し、「native AOT発行を有効にする」にチェックを入れて「作成」を押します。
- コードを記述します。
- プロジェクトを右クリックして「発行」を選択します。発行メニューがない場合は、一度Visual Studio Installerで「.NET デスクトップ開発」のみを選択状態にして変更。その後再度Visual Studio Installerを立ち上げて「C++によるデスクトップ開発」にチェックを入れて変更を実施してみてください。
- フォルダを選択し次へ。
- フォルダを選択し次へ。
- 出力先を設定し「完了」を押します。
- 「閉じる」を押します。
- 「すべての設定を表示」を押します。
- 「配置モード」と「ターゲット ランタイム」を選択して「保存」を押します。
- 「発行」を押します。処理が完了したら、出力先にアプリがあることを確認します。