There's a related answer here where @DeepSpace101 mentions:
Also, the location of app.config at runtime is different than what was in .net framework, instead of "projectName.exe.config". It is now "projectName.dll.config" in .net core.
I recently ran into this problem after migrating some WinForms apps from .NET Framework 4.8 to .NET 7. I noticed that all my settings were returning default values even when the .exe.config file contained an explicit override value. I first tried to see which config file the app was loading based on this answer, but AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
isn't available in .NET "Core". Then based on another answer, I checked ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath
, which confirmed the app was loading from projectName.dll.config instead of projectName.exe.config.
Fortunately, I found a good workaround based on this answer and this GitHub issue. ConfigurationManager supports an APP_CONFIG_FILE key for AppDomain.SetData
to override the .config file as long as it is called before any ConfigurationManager code is executed. I've made a utility function that I call from all of my WinForms .exes as the first line in their Program's Main()
entry point:
/// <summary>
/// Overrides .NET's Core's ConfigurationManager to use AppName.exe.config instead
/// of AppName.dll.config.
/// </summary>
/// <param name="exeConfigName">An optional name of an .exe.config file to use.
/// If null, then the entry assembly's file name without extension is used with
/// ".exe.config" appended.</param>
/// <remarks>
/// For this to take effect, this method must be called before any application code
/// pulls a configuration value.
/// </remarks>
public static void UseExeConfig(string? exeConfigName = null)
{
// .NET Framework and Core support using APP_CONFIG_FILE to override which .config
// file an app reads its settings from.
// https://github.com/dotnet/runtime/pull/56748#discussion_r682287640
//
// Note 1: This .exe.config override only affects some sections of the file. Anything
// read by the CLR host before the app starts (e.g., settings in the <runtime> section
// like <gcServer>) will only be read from the app's default config file.
// https://mcmap.net/q/435017/-relocating-app-config-file-to-a-custom-path/12708388#12708388
// However, that's only an issue for .NET Framework since .NET Core reads its CLR host
// runtime settings from other places. https://learn.microsoft.com/en-us/dotnet/core/runtime-config/
//
// Note 2: We have to be careful to only reference base CLR methods here and not use
// anything from referenced assemblies. If we run any code that pulls a configuration
// setting before we change APP_CONFIG_FILE, then our change will be ignored.
string? entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location;
if (entryAssemblyLocation != null)
{
string entryAssemblyFile = Path.GetFileName(entryAssemblyLocation);
string entryConfigName = entryAssemblyFile + ".config";
exeConfigName ??= Path.GetFileNameWithoutExtension(entryAssemblyFile) + ".exe.config";
if (!entryConfigName.Equals(exeConfigName, StringComparison.OrdinalIgnoreCase))
{
string basePath = Path.GetDirectoryName(entryAssemblyLocation) ?? string.Empty;
string exeConfigFilePath = Path.Combine(basePath, exeConfigName);
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", exeConfigFilePath);
}
}
}
This technique can also be used to force multiple applications to share a single .config file. For example, if you want Service.exe and Worker.exe to both look at Service.exe.config, then call UseExeConfig("Service.exe.config")
from each of their Main methods. That allows IT/Support to only have to configure connection strings in one place.
My.Settings
(it has the normal properties but getting them raises an exception): I gather from here that the issue comes from a<system.diagnostics>
section in the config file that shouldn't be here and can be deleted manually. (It's regenerated by rebuilds as said in the linked page, but thankfully, in my experience, not by solution builds.) – Brandes