使用 .Net Core 3.0 发布独立的 exe 文件并使用 app.config
Publishing a standalone exe file with .Net Core 3.0 and using an app.config
我有一个 .Net Core 3.0 项目,想利用新选项将项目发布为单个 .exe 文件。
我用命令
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
这确实生成了一个 .exe 文件,但问题是我的项目中有一个 app.config 文件,用户应该修改它,我不确定它是否被打包在 .exe 中,还有。当我测试生成的 .exe 时,它会读取我最初放入 app.config.
中的值
我已经尝试将 "Copy to Output Directory" 选项设置为 "Copy always" 但这并没有改变任何东西。 "Build action" 设置为 "None"。
我如何设置它,以便将 app.config 以外的所有内容打包到该 .exe 文件中,以便用户可以更改值?
您应该在项目设置中将文件标记为 <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
短版
.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
。 .NET Core 的配置系统在 Configuration in ASP.NET Core 中进行了描述,尽管名称如此,但适用于每个 .NET Core 应用程序。它也更强大,从多个来源加载配置,包括文件(甚至 INI)、数据库、Azure 或 AWS 设置存储等。
在 VS 2019 和命令行中将 Application Configuration File
添加到新的 Windows Forms 项目会创建一个 App1.config
文件,就 VS 或 .NET 而言没有特殊意义核心很关心。创建 AppName.exe.config
实际上需要使用生产设置创建一个新的 AppName.exe.config
文件。
读取旧式 .config
文件的唯一方法是使用 ConfigurationManager.OpenExeConfiguration 显式加载它。这只是加载文件并解析它。可以传递任何文件路径,或指定一个 ConfigurationUserLevel,它根据可执行文件的基本目录简单地解析为文件位置。
问题就在这里。有 a bug.
对于单文件可执行文件,所有文件都捆绑在一个扩展名为 .exe
的主机文件中。当该文件 运行 第一次出现时,它将其内容解压缩到 AppData\Local\Temp\.net\
,在一个以应用程序命名的新文件夹中。 By design, the application's base directory should be the host's path, where the single .exe is. Unfortunately, there's a bug 和基本目录仍然是包的位置,.dll
实际上是主机 运行。
这就是为什么
System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None).FilePath
returns C:\Users\myUser~1\AppData\Local\Temp\.net\ConsoleApp_NetCore\nk5sdmz5.ym1\ConsoleApp_NetCore.dll.config
我敢打赌 AppContext.BaseDirectory
returns 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 文件提供程序来完成。
这适用于我的独立 exe。
在我的 .csproj 文件中,我添加了这个,它在构建时创建了 myProgramName.dll.config。
<ItemGroup>
<None Update="App.config">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
</ItemGroup>
在我的 C# 控制台应用程序代码 (dot net core 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
我有一个 .Net Core 3.0 项目,想利用新选项将项目发布为单个 .exe 文件。
我用命令
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
这确实生成了一个 .exe 文件,但问题是我的项目中有一个 app.config 文件,用户应该修改它,我不确定它是否被打包在 .exe 中,还有。当我测试生成的 .exe 时,它会读取我最初放入 app.config.
中的值我已经尝试将 "Copy to Output Directory" 选项设置为 "Copy always" 但这并没有改变任何东西。 "Build action" 设置为 "None"。
我如何设置它,以便将 app.config 以外的所有内容打包到该 .exe 文件中,以便用户可以更改值?
您应该在项目设置中将文件标记为 <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
短版
.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
。 .NET Core 的配置系统在 Configuration in ASP.NET Core 中进行了描述,尽管名称如此,但适用于每个 .NET Core 应用程序。它也更强大,从多个来源加载配置,包括文件(甚至 INI)、数据库、Azure 或 AWS 设置存储等。
在 VS 2019 和命令行中将 Application Configuration File
添加到新的 Windows Forms 项目会创建一个 App1.config
文件,就 VS 或 .NET 而言没有特殊意义核心很关心。创建 AppName.exe.config
实际上需要使用生产设置创建一个新的 AppName.exe.config
文件。
读取旧式 .config
文件的唯一方法是使用 ConfigurationManager.OpenExeConfiguration 显式加载它。这只是加载文件并解析它。可以传递任何文件路径,或指定一个 ConfigurationUserLevel,它根据可执行文件的基本目录简单地解析为文件位置。
问题就在这里。有 a bug.
对于单文件可执行文件,所有文件都捆绑在一个扩展名为 .exe
的主机文件中。当该文件 运行 第一次出现时,它将其内容解压缩到 AppData\Local\Temp\.net\
,在一个以应用程序命名的新文件夹中。 By design, the application's base directory should be the host's path, where the single .exe is. Unfortunately, there's a bug 和基本目录仍然是包的位置,.dll
实际上是主机 运行。
这就是为什么
System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None).FilePath
returns C:\Users\myUser~1\AppData\Local\Temp\.net\ConsoleApp_NetCore\nk5sdmz5.ym1\ConsoleApp_NetCore.dll.config
我敢打赌 AppContext.BaseDirectory
returns 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 文件提供程序来完成。
这适用于我的独立 exe。 在我的 .csproj 文件中,我添加了这个,它在构建时创建了 myProgramName.dll.config。
<ItemGroup>
<None Update="App.config">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</None>
</ItemGroup>
在我的 C# 控制台应用程序代码 (dot net core 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