使用.Net Core 3.0并使用app.config

时间:2019-10-17 11:01:49

标签: c# .net-core app-config

我有一个.Net Core 3.0项目,想利用新选项将项目发布为单个.exe文件。

我使用命令
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true

这肯定会产生一个.exe文件,但是问题是我的项目中有一个app.config文件,用户应修改该文件,而且我不确定它是否也打包在.exe中。当我测试生成的.exe时,它会读取我最初放在app.config中的值。

我尝试将“复制到输出目录”选项设置为“始终复制”,但这没有任何改变。 “构建操作”设置为“无”。

如何设置它,以便将app.config以外的所有内容打包到该.exe文件中,以便用户可以更改值?

3 个答案:

答案 0 :(得分:3)

简短版本

.NET Core不使用app.config,您必须升级到新的配置系统或手动管理文件。

  1. <ExcludeFromSingleFile>true</ExcludeFromSingleFile>添加到App1.config文件中以使其脱离捆绑包。
  2. 手动使用生产设置添加一个MyApp.exe.config文件,并添加<CopyToPublishDirectory>Always</CopyToPublishDirectory>使其发布到Publish目录中。转换不会运行,因此请确保其中包含所需的所有内容。
  3. 最后明确地加载文件,以避免应用程序的基本路径解析中的错误
var hostFile=Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
ConfigurationManager.OpenExeConfiguration(hostFile+".config");

要加载已发布的文件,就像其他文件一样


.NET Core 3(即使是Windows窗体)也不使用app.configConfiguration in ASP.NET Core中描述了.NET Core的配置系统,尽管名称如此,但它适用于每个.NET Core应用程序。它的功能也要强大得多,可以从多个来源加载配置,包括文件(甚至是INI),数据库,Azure或AWS设置存储等。

在VS 2019和命令行中,将Application Configuration File添加到新的Windows Forms项目中,就VS或.NET Core而言,没有特殊意义的App1.config文件。创建AppName.exe.config时,实际上需要使用生产设置来创建一个新的AppName.exe.config文件。

读取旧式.config文件的唯一方法是显式加载ConfigurationManager.OpenExeConfiguration。这只是加载文件并对其进行分析。可以传递任何文件路径,也可以指定ConfigurationUserLevel,它仅基于可执行文件的基本目录解析为文件位置。

这是麻烦开始的地方。有a bug.

对于单文件可执行文件,所有文件都捆绑在扩展名为.exe的单个主机文件中。首次运行该文件时,它将其内容解压缩到AppData\Local\Temp\.net\的新文件夹中,该文件夹名为该应用程序。 By design,应用程序的基本目录应为主机的路径,单个.exe所在。不幸的是,there's a bug和基本目录仍然是包和主机实际运行的.dll的位置。

这就是为什么

System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None).FilePath 

返回C:\Users\myUser~1\AppData\Local\Temp\.net\ConsoleApp_NetCore\nk5sdmz5.ym1\ConsoleApp_NetCore.dll.config,我敢打赌AppContext.BaseDirectory返回C:\Users\myUser~1\AppData\Local\Temp\.net\ConsoleApp_NetCore\nk5sdmz5.ym1\

解决方法 用于检索主机的路径并显式加载设置文件。这意味着我们现在可以使用任何文件名。如果我们遵循命名文件appname.exe.config的旧约定,则只需将.config附加到主机的完整路径即可:

var hostFile=Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
ConfigurationManager.OpenExeConfiguration(hostFile+".config");

这也必须使用.NET Core File提供程序来完成。

答案 1 :(得分:1)

您应该在项目设置中将文件标记为<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

https://github.com/dotnet/core-setup/issues/7738 https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md#build-system-interface

答案 2 :(得分:1)

这对我来说适用于独立exe。 在我的.csproj文件中,添加了此文件,该文件在构建时创建了myProgramName.dll.config。

<ItemGroup>
 <None Update="App.config">
    <CopyToOutputDirectory>Never</CopyToOutputDirectory>
    <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
 </None>
</ItemGroup>

然后在我的C#控制台应用程序代码(点网核心3.1.0)中添加了它。

// requires using System.Configuration;
string programName = "myProgramName"; 
var sourceHostFile = Directory.GetCurrentDirectory() + @"\" + programName + @".dll.config";
Console.WriteLine("sourceHostFile is: " + sourceHostFile);
// to load yourProgram.dll.config
// With Single-file executables, all files are bundled in a single host file with the .exe extension. 
// When that file runs for the first time, it unpacks its contents to AppData\Local\Temp\.net\, in a new folder named for the application
var targetHostFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;
// ignore when in debug mode in vs ide
if (sourceHostFile != targetHostFile)
{
File.Copy(sourceHostFile, targetHostFile, true);
}
Console.WriteLine("targetHostFile is: " + targetHostFile);
string password = ConfigurationManager.AppSettings["password"];
Console.WriteLine("password from config is: " + password);
// end of poc