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?
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.