2

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. mscorrc.dll

  • 1
    There's no `user.config` or `app.config` in general in .NET Core. And .NET 5 *is* .NET Core 5. If you want to use the old configuration classes as a temporary fix you can add the [System.Configuration.ConfigurationManagement](https://www.nuget.org/packages/System.Configuration.ConfigurationManager/) package but long term you'll have to migrate to .NET Core's configuration system. Which, by the way, is a lot easier to cusomize and use. Right now you're using a hard-coded reference to a very specific assembly's `Settings` class – Panagiotis Kanavos Nov 16 '20 at 09:30
  • Adding **System.Configuration.ConfigurationManagement** package didn't help. The current system with the Settings class suited me very well, since my application just stores some unimportant user settings. Also, this file is automatically created when the application is first launched, so there is no need to store the settings file separately near executable file and generally write any code to implement the creation and reading of the file. – Sindeev Victor Nov 16 '20 at 09:56
  • 1
    Also, I can't understand why it does not work correctly ONLY when using Single File publish. – Sindeev Victor Nov 16 '20 at 10:00
  • [There are how it's looks](https://i.imgur.com/CeYP6RI.png) when mscorrc.dll in folder. – Sindeev Victor Nov 16 '20 at 10:11
  • There's nothing to add to `there's no app.config in .NET Core`. The exception message you posted complains about a missing executable though, not a missing `config` file. Post the exception as *text*, not an image. Images can't be googled. It's quite likely someone's faced the same problem before. You're working with a legacy, custom configuration system now. In .NET Core 3.1, SPF exe was a package containing binaries that got extracted to some path. In .NET 5, an SPF exe is single linked executable. Perhaps and updated `ConfigurationManagement` package can take care of this – Panagiotis Kanavos Nov 16 '20 at 10:22
  • What does your `csproj` look like? Post it in the question as **text**. Same for the exception text. You can copy the messagebox text with Ctrl+C, although the *full* exception text would be a lot more useful. The message or an inner exception may contain an explanation. You can get the entire exception with `Exception.ToString()` – Panagiotis Kanavos Nov 16 '20 at 10:24
  • It is already `Exception.ToString()`. Added in question as a text. + added project file – Sindeev Victor Nov 16 '20 at 10:33

1 Answers1

1

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.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236