はじめに
この記事でp:PublishSingleFile
をtrueで作ったときに気づいたのですが、.NET 5では自己完結型アプリケーションでビルドしたアプリを実行した場合に実行ディレクトリが.NET Core 3.1の時と異なる&実行ファイルパスがAssembly.GetExecutingAssembly().Location
では取得できませんでした。
この記事では.NET 5でPublishSingleFileを指定してビルドした自己完結型アプリケーションで、実行ディレクトリを取得する方法を確認します。
自己完結型アプリケーションの形式でアプリをビルドして、それぞれ実行する。
.NET 5および.NET Core 3.1のコンソールアプリケーションを作成し、それぞれメイン関数に下記のコードを記載します。
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"Environment.Version={Environment.Version}");
Console.WriteLine($"Assembly.GetExecutingAssembly().Location={Assembly.GetExecutingAssembly().Location}");
Console.WriteLine($"AppContext.BaseDirectory={AppContext.BaseDirectory}");
Console.WriteLine("Hello World!");
Console.ReadLine();
}
}
それぞれのプロジェクトを下記のコマンドラインでアプリを自己完結型アプリケーションでビルドします。
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
実行したファイルをc:\temp
においてからダブルクリックで実行したら下記の結果になりました。
ランタイム | Assembly.GetExecutingAssembly().Location | AppContext.BaseDirectory |
---|---|---|
.NET 5 | 空 | C:\temp\sample\AppUsing5.exe |
.NET Core 3.1 | %LOCALAPPDATA%\Temp.net\AppUsingCore3\dl4pjkfu.bol\AppUsingCore3.dll | C:\temp\sample\AppUsingCore3.exe |
.NET 5で実行ファイルのパスを求めるには?
単一ファイルの配置と実行可能ファイルにAPI の非互換性として、.NET 5で自己完結型アプリケーションでビルドした場合にAssembly.Locationでは空を返すとしっかり記載されていますね。また、Assembly.GetFile
やAssembly.CodeBase
では例外を返すとも記載されています。
実行ファイルのディレクトリを参照する場合は、AppContext.BaseDirectoryを使うのが正しいようです。
自己完結型アプリケーションの実行ディレクトリ
.NET 3.1ではZIP形式の自己完結型アプリケーションは、一度%LOCALAPPDATA%に展開された後に展開された場所からプログラムが起動されます。このため実行ディレクトリを参照する場合にはAssembly.GetExecutingAssembly().Location
などを確認する必要があったし、実行ファイルが存在するディレクトリを確認する場合はAppContext.BaseDirectory
を使うなどの使い分けが必要でした。
.NET 5では一時ディレクトリに展開されず、アプリが配置された場所から直に実行されるようになります。
まとめ
.NET 5になって実行パスの取得方法がわかりやすくなりましたね。
実行ファイルのパスの取得方法について、MSのドキュメントで触れられるのは初めてなんじゃないでしょうか