I'm trying to migrate WPF project from .NET Core 3.1 to .NET 5.0. My project uses default properties file (user.config) to store some app data.
Project code:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
try
{
Properties.Settings.Default.test = "Edited";
Properties.Settings.Default.Save();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
}
After publishing the project, I get an System.IO.FileNotFoundException (The specified file could not be found) when trying to access to Properties.Settings.Default.
---------------------------
---------------------------
System.IO.FileNotFoundException: Не удается найти указанный файл. (0x80070002)
at System.Reflection.RuntimeModule.GetFullyQualifiedName()
at System.Reflection.RuntimeModule.get_Name()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.Internal.ConfigurationManagerInternal.System.Configuration.Internal.IConfigurationManagerInternal.get_ExeProductName()
at System.Configuration.ApplicationSettingsBase.get_Initializer()
at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propertyInfo)
at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
at System.Configuration.ApplicationSettingsBase.get_Properties()
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at WpfApp1.Properties.Settings.get_test()
at WpfApp1.MainWindow..ctor()
---------------------------
ОК
---------------------------
The problem only happens when using Single File publishing.
My publish properties:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net5.0\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net5.0-windows</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>True</PublishReadyToRun>
<PublishTrimmed>False</PublishTrimmed>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
</Project>
Settings class:
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("123")]
public string test {
get {
return ((string)(this["test"]));
}
set {
this["test"] = value;
}
}
}
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
</PropertyGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>
Note 1: I have check %userprofile%\appdata\local folder and it not create user.config file after launching the app.
Note 2: If i put the mscorrc.dll to publish folder then all is work fine.
Looks there's a bug in .NET 5's handling of legacy settings when single-file publishing is used. The linked Github issue shows that trying to read any setting, not just user settings, results in a System.IO.FileNotFoundException
. The fix for this wasn't included in .NET 5.0.
From the issue:
A workaround is to set
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
Long-term, you'll have to move to .NET Core's configuration system anyway. app.config
and user.config
are legacy technologies and issues like this are to be expected.
User contributions licensed under CC BY-SA 3.0