我有一个.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文件中,以便用户可以更改值?
答案 0 :(得分:3)
简短版本
.NET Core不使用app.config
,您必须升级到新的配置系统或手动管理文件。
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
添加到App1.config
文件中以使其脱离捆绑包。 MyApp.exe.config
文件,并添加<CopyToPublishDirectory>Always</CopyToPublishDirectory>
使其发布到Publish
目录中。转换不会运行,因此请确保其中包含所需的所有内容。var hostFile=Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
ConfigurationManager.OpenExeConfiguration(hostFile+".config");
要加载已发布的文件,就像其他文件一样
.NET Core 3(即使是Windows窗体)也不使用app.config
。 Configuration 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