単一ファイル.Net Core 3.0 Web APIアプリケーションは、単一ファイルアプリケーションのビルド先と同じディレクトリにある_appsettings.json
_ファイルを探すようにどのように構成する必要がありますか?
実行した後
_dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
_
ディレクトリは次のようになります。
_XX/XX/XXXX XX:XX PM <DIR> .
XX/XX/XXXX XX:XX PM <DIR> ..
XX/XX/XXXX XX:XX PM 134 appsettings.json
XX/XX/XXXX XX:XX PM 92,899,983 APPNAME.exe
XX/XX/XXXX XX:XX PM 541 web.config
3 File(s) 92,900,658 bytes
_
ただし、_APPNAME.exe
_を実行しようとすると、次のエラーが発生します
_An exception occurred, System.IO.FileNotFoundException: The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Users\USERNAME\AppData\Local\Temp\.net\APPNAME\kyl3yc02.5zs\appsettings.json'.
at Microsoft.Extensions.Configuration.FileConfigurationProvider.HandleException(ExceptionDispatchInfo info)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
...
_
似ているが明確な質問 からの解決策、および他のスタックオーバーフローの質問を試しました。
以下をSetBasePath()
に渡そうとしました
Directory.GetCurrentDirectory()
_environment.ContentRootPath
_
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
それぞれが同じエラーにつながりました。
問題の根本は、PublishSingleFile
バイナリが解凍され、temp
ディレクトリから実行されることです。
この単一ファイルアプリの場合、_appsettings.json
_が探していた場所は次のディレクトリでした。
_C:\Users\USERNAME\AppData\Local\Temp\.net\APPNAME\kyl3yc02.5zs
_
上記のすべての方法は、ファイルの解凍先を指します。これは、実行された場所とは異なります。
GitHub here に_PublishSingleFile excluding appsettings not working as expected
_というタイトルの問題が見つかりました。
それは別の問題を指摘しました here _single file publish: AppContext.BaseDirectory doesn't point to apphost directory
_というタイトル
その中で、解決策はProcess.GetCurrentProcess().MainModule.FileName
を試すことでした
次のコードは、バイナリが抽出された場所ではなく、単一実行可能アプリケーションが実行されたディレクトリを参照するようにアプリケーションを構成しました。
_config.SetBasePath(GetBasePath());
config.AddJsonFile("appsettings.json", false);
_
GetBasePath()
の実装:
_private string GetBasePath()
{
using var processModule = Process.GetCurrentProcess().MainModule;
return Path.GetDirectoryName(processModule?.FileName);
}
_
実行可能ファイルの外で実行時にファイルを使用することに問題がない場合は、csprojで、必要なファイルにフラグを付けるだけです。この方法では、既知の場所でライブ変更などを行うことができます。
<ItemGroup>
<None Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
<None Include="appsettings.Development.json;appsettings.QA.json;appsettings.Production.json;">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<DependentUpon>appsettings.json</DependentUpon>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Views\Test.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
</ItemGroup>
これが受け入れられず、ファイルが1つだけでなければならない場合は、ホストセットアップで、単一ファイル抽出パスをルートパスとして渡します。これにより、構成とかみそり(後で追加)が通常どおりファイルを見つけることができます。
// when using single file exe, the hosts config loader defaults to GetCurrentDirectory
// which is where the exe is, not where the bundle (with appsettings) has been extracted.
// when running in debug (from output folder) there is effectively no difference
var realPath = Directory.GetParent(System.Reflection.Assembly.GetExecutingAssembly().Location).FullName;
var Host = Host.CreateDefaultBuilder(args).UseContentRoot(realPath);
本当に単一のファイルを作成し、PDBを作成しないためには、以下も必要です。
<DebugType>None</DebugType>