4

I have many user scoped settings being stored in user.config by objects which inherit from ApplicationSettingsBase.

The SettingsKey for each instance is derived dynamically at runtime using primarily the form name. Therefore there could be hundreds.

I've read many questions and answers (Like this one - How do you keep user.config settings across different assembly versions in .net?) which all recommend wrapping a ApplicationSettingsBase.Upgrade() call in some version number checking.

The problem is (as far as I can tell) you need to know every single *SettingsKey( value used in order to instantiate all the ApplicationSettingsBase objects to in turn call the upgrade method.

Is there a way to upgrade all user.config settings at once or alternatively, iterate through all settings in the file to upgrade them?

Community
  • 1
  • 1
Stuart Helwig
  • 9,318
  • 8
  • 51
  • 67
  • Its just an XML file, right? – Jeremy Thompson Feb 13 '13 at 00:45
  • 1
    Yes Jeremy it's Xml and that's the track I've started down this morning. It is an Xml file, however, with each new version of the application, a new Xml file is created in a new folder within the users profile. Currently, I'm locating the old Xml file and working on reading the userSettings nodes in order to instantiate all the relevant settings objects. It feels "hacky" though and I am wondering if there is a better way. (When I asked te question I hadn't started down this track). I will post results if nothing better is suggested. – Stuart Helwig Feb 13 '13 at 01:03
  • I think this is a duplicate of http://stackoverflow.com/questions/534261/how-do-you-keep-user-config-settings-across-different-assembly-versions-in-net (which has a much better answer than the accepted answer here). – Jeff Roe Jun 16 '14 at 16:49
  • 1
    The answer to that question (linked in the question btw) and others like it doesn't seem to work for custom application settings stored in the user.config file, by classes inheriting from ApplicationSettingsBase. Is there a way to upgrade all those settings too, using this method. I agree it's way cleaner, but at the moment of have literally hundreds of settings stored here. – Stuart Helwig Jun 17 '14 at 03:28
  • See [http://stackoverflow.com/questions/534261](http://stackoverflow.com/questions/534261) – Sam Apr 26 '16 at 07:59

1 Answers1

2

The approach I have come up with is something of a hack I feel, but too many approaches have failed and I need to get on with things :-(

I have resorted to copying the previous version of the user.config in the event of a new version running.

Firstly, determine whether or not an upgrade is required, like so many variants of this question recommend.

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
Version version = assembly.GetName().Version;

if (version.ToString() != Properties.Settings.Default.ApplicationVersion)
{
    copyLastUserConfig(version);
}

then, to copy the last user.config....

private static void copyLastUserConfig(Version currentVersion)
{
try
{
    string userConfigFileName = "user.config";


    // Expected location of the current user config
    DirectoryInfo currentVersionConfigFileDir = new FileInfo(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath).Directory;
    if (currentVersionConfigFileDir == null)
    {
        return;
    }

    // Location of the previous user config

    // grab the most recent folder from the list of user's settings folders, prior to the current version
    var previousSettingsDir = (from dir in currentVersionConfigFileDir.Parent.GetDirectories()
                               let dirVer = new { Dir = dir, Ver = new Version(dir.Name) }
                               where dirVer.Ver < currentVersion
                               orderby dirVer.Ver descending
                               select dir).FirstOrDefault();

    if (previousSettingsDir == null)
    {
        // none found, nothing to do - first time app has run, let it build a new one
        return;
    }

    string previousVersionConfigFile = string.Concat(previousSettingsDir.FullName, @"\", userConfigFileName);
    string currentVersionConfigFile = string.Concat(currentVersionConfigFileDir.FullName, @"\", userConfigFileName);

    if (!currentVersionConfigFileDir.Exists)
    {
        Directory.CreateDirectory(currentVersionConfigFileDir.FullName);
    }

    File.Copy(previousVersionConfigFile, currentVersionConfigFile, true);

}
catch (Exception ex)
{
    HandleError("An error occurred while trying to upgrade your user specific settings for the new version. The program will continue to run, however user preferences such as screen sizes, locations etc will need to be reset.", ex);
}
}

Thanks to Allon Guralnek on his answer to this question (How do you upgrade Settings.settings when the stored data type changes?) for the Linq in the middle which gets the PreviousSettingsDir.

Community
  • 1
  • 1
Stuart Helwig
  • 9,318
  • 8
  • 51
  • 67