5

I have an application that uses a custom configuration section for user-level settings. It's done this way instead of using Settings files so that the settings can be centralized in a single app.config for the program, instead of having one per project as is the default for settings files.

The problem is that these custom settings are configurable per-user, and are lost when the user upgrades the software (a new folder for the new build version is created, and the old folder is no longer used). So, I need a way to migrate these settings either on update, or on the first run of the application per user after the upgrade. I've seen the info on Settings.Upgrade(), but that only works specifically on the Settings file section of the config. I've looked through documentation for ConfigurationSection (from which my custom settings class/section derives) and there doesn't seem to be anything helpful. Using ConfigurationManager to pull in the user settings from the installer to migrate them seems to be a dead-end, as the overloads of OpenExeConfiguration don't support specifying both the executable and the user level.

Any hints? The information stored is not critical (remembered window geometry and layout settings, mostly) but can be annoying to lose every time the app is upgraded. The only thing I can think of is to forego the config mechanism for these settings altogether, and implement my own model for storing these settings in version-agnostic files in the user's AppData (where I store a few other user-specific files). I would prefer that to be the last option, as you lose a lot by giving up the app.config wrappers.

KeithS
  • 70,210
  • 21
  • 112
  • 164

2 Answers2

1

This is an old question but I'll write an answer in case anyone ends up here via Google.

I "solved" this issue by forcefully remembering the previous version's file path and overriding the file in the new config location with the old file.

I'm sure there are many flaws with this approach but if you're looking for a quick solution that might work then you may find this useful.

if (Settings.Default.IsNewVersion)
{
    Settings.Default.Upgrade();
    var targetConfigPath = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath;

    if (!string.IsNullOrWhiteSpace(Settings.Default.ConfigPath))
    {
        System.IO.File.Copy(Settings.Default.ConfigPath, targetConfigPath, true);
        Settings.Default.Reload();
    }

    Settings.Default.ConfigPath = targetConfigPath;
    Settings.Default.IsNewVersion = false;

    Settings.Default.Save();
}
Jas Laferriere
  • 804
  • 10
  • 12
  • This is actually brilliant. I could not find a better solution when the user settings file contains custom sections for lists like recent file lists. A downside though is that the user must run the program at least once to save the previous ConfigPath setting before you can safely upgrade the settings. Maybe there is a way to get the previous path before it automatically changes. – Scott Hutchinson Jun 14 '23 at 18:57
1

You might want to create a reference to an external configuration section file that stays in tact during an update. Use the configSource attribute to reference the file.

That way users can keep their settings when the app.config is updated.

This is a related post: How to enable configSource attribute for Custom Configuration Section in .NET?

Community
  • 1
  • 1
mzwaal
  • 154
  • 6
  • I'm already doing that, actually, and it works great for "application-level" settings. The problem is that when settings are saved at the user level, they go into an AppData folder that is specific not only to the app but the current version. This makes sure that an existing config file doesn't break the program if changes were made to the expected structure of said file in a new version, but it also means that I cannot access the data from the file for the old version using the configuration classes; I have to go find the file directly, which is not ideal to say the least. – KeithS Jun 06 '11 at 15:25
  • Perhaps if you store the setting here, you can access them in a way that is not version dependant: http://stackoverflow.com/questions/1572442/saving-a-file-to-application-data-in-c – mzwaal Jun 07 '11 at 12:02
  • Saving config settings at the user level saves them to User/AppData/Roaming; that's just where it happens. Beyond that, it's up to the framework to decide exactly where. Overriding that apparently requires rolling my own configuration persistence mechanism. – KeithS Jun 08 '11 at 17:40