プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2019/12/23

[.NET Core] PublishSingleFile 有効時の実行パス

update2019/12/27 event_note2019/12/23 6:06

.NET Core 3.0 以降では PublishSingleFile=true で単一の実行可能ファイル(Windows では exe ファイル)にしてビルド出力が可能です。

しかし、設定ファイルなどを exe ファイルと同じディレクトリに置いて読み込むようにしている場合などはちょっと注意が必要です。

単一の実行可能ファイルであっても、実行時には Temp ディレクトリにファイルを展開してから実行するという方法を取っているようで、実行パスが Temp ディレクトリになってしまうからです。

参考程度に、Windows 環境でのパスの取得結果を載せます。

環境

  • Visual Studio 2019 (16.4.2)
  • .NET Core 3.0 (ASP.NET Core 3.0)

サンプルコード

// Directory.GetCurrentDirectory() を使った場合
Console.WriteLine(Directory.GetCurrentDirectory());

// AppContext.BaseDirectory を使った場合
Console.WriteLine(AppContext.BaseDirectory);

// Process.GetCurrentProcess().MainModule を使った場合
using var processModule = Process.GetCurrentProcess().MainModule;
Console.WriteLine(processModule?.FileName);
Console.WriteLine(Path.GetDirectoryName(processModule?.FileName));

// Assembly.GetExecutingAssembly() を使った場合
Console.WriteLine(Assembly.GetExecutingAssembly().Location);
Console.WriteLine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

デバッグ時の出力結果

Visual Studio のデバッガを使用した場合、以下のような出力となります。

// Directory.GetCurrentDirectory() を使った場合
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1

// AppContext.BaseDirectory を使った場合
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1\

// Process.GetCurrentProcess().MainModule を使った場合
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1\ConsoleApp1.exe
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1

// Assembly.GetExecutingAssembly() を使った場合
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1\ConsoleApp1.dll
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1

基本的に全て同じパスを指します。

単一の実行可能ファイルとして出力したときの出力結果

カレントパス C:\Users\username からリリースビルドした exe を実行した場合、以下のような出力になります。

// Directory.GetCurrentDirectory() を使った場合
C:\Users\username

// AppContext.BaseDirectory を使った場合
C:\Users\username\AppData\Local\Temp\.net\ConsoleApp1\ord2bgux.ncl\

// Process.GetCurrentProcess().MainModule を使った場合
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Release\netcoreapp3.1\win-x64\publish\ConsoleApp1.exe
C:\Users\username\Source\Repos\ConsoleApp1\ConsoleApp1\bin\Release\netcoreapp3.1\win-x64\publish

// Assembly.GetExecutingAssembly() を使った場合
C:\Users\username\AppData\Local\Temp\.net\ConsoleApp1\ord2bgux.ncl\ConsoleApp1.dll
C:\Users\username\AppData\Local\Temp\.net\ConsoleApp1\ord2bgux.ncl

実行パスは Temp ディレクトリとなります。
従って、exe がある場所を取得したい場合は Process.GetCurrentProcess().MainModule を使う必要があります。