ApplicationSettingsBase.Upgrade() Not Upgrading User Settings after Recompiling with .NET 4.0
I have a C# program that is using the standard ApplicationSettingsBase
to save its user settings. This was working fine under .NET 3.5. And the provided Upgrade()
method would properly "reload" those settings whenever a new version of my program was created.
Recently, I recompiled the program with .NET 4.0. My program's version number also increased. But, when I run this version, Upgrade()
doesn't seem to to detect any previous version settings, and does not "reload" them. It starts blank.
As 开发者_运维知识库a test, I recompiled yet again, going back to .NET 3.5. And this time, the Upgrade()
method started working again.
Is there a way to allow Upgrade()
to work when switching frameworks? Is there something else I am missing?
I had exactly the same problem, and again I tested this several times from .NET 3.5 recomplied to .NET 4.0.
Unfortunately, my solution is in vb.net, but I'm sure you can use one of the many conversion programs to see this in c# such as http://www.developerfusion.com/tools/convert/vb-to-csharp/
It involves enumerating through all the folders in %AppData%\CompanyName to find the latest user.config file in a folder name of the version you wish to upgrade from.
I found that recompiling my app to .NET 4.0 under Visual Studio 2010 would create a new folder of name %AppData%\CompanyName\AppName.exe_Url_blahbahblah even though I had changed absolutely no other settings or code at all!
All my previous releases prior to .NET 4.0 retained the same folder name and upgraded successfully. Copying the old user.config file (and version folder name) from the old folder into the new folder structure created under .NET 4.0 (with the old version folder name) fixes the problem - it will now upgrade.
This example assumes you have a user setting named IUpgraded which is set to False by default (and later set to True) to check to see if the settings are initial defalt values or not - you may use any other variable you created instead. The example shows upgrading from version 1.2.0.0 to something later which you can change by changing the value of lastVersion.
The code is to be placed at the top of the form Load event of your latest (.NET 4.0) application version:
Imports System
Imports System.IO
If Not My.Settings.IUpgraded Then 'Upgrade application settings from previous version
My.Settings.Upgrade()
'The following routine is only relevant upgrading version 1.2.0.0
If Not My.Settings.IUpgraded Then 'enumerate AppData folder to find previous versions
Dim lastVersion As String = "1.2.0.0" 'version to upgrade settings from
Dim config_initial As System.Configuration.Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal)
Dim fpath As String = config_initial.FilePath
For x = 1 To 3 'recurse backwards to find root CompanyName folder
fpath = fpath.Substring(0, InStrRev(fpath, "\", Len(fpath) - 1))
Next
fpath = fpath.Substring(0, Len(fpath) - 1) 'remove trailing backslash
Dim latestConfig As FileInfo 'If not set then no previous info found
Dim di As DirectoryInfo = New DirectoryInfo(fpath)
If di.Exists Then
For Each diSubDir As DirectoryInfo In di.GetDirectories(lastVersion, SearchOption.AllDirectories)
If InStr(diSubDir.FullName, ".vshost") = 0 Then 'don't find VS runtime copies
Dim files() As FileInfo = diSubDir.GetFiles("user.config", SearchOption.TopDirectoryOnly)
For Each File As FileInfo In files
Try
If File.LastWriteTime > latestConfig.LastWriteTime Then
latestConfig = File
End If
Catch
latestConfig = File
End Try
Next
End If
Next
End If
Try
If latestConfig.Exists Then
Dim newPath As String = config_initial.FilePath
newPath = newPath.Substring(0, InStrRev(newPath, "\", Len(newPath) - 1))
newPath = newPath.Substring(0, InStrRev(newPath, "\", Len(newPath) - 1))
newPath &= lastVersion
If Directory.Exists(newPath) = False Then
Directory.CreateDirectory(newPath)
End If
latestConfig.CopyTo(newPath & "\user.config")
My.Settings.Upgrade() 'Try upgrading again now old user.config exists in correct place
End If
Catch : End Try
End If
My.Settings.IUpgraded = True 'Always set this to avoid potential upgrade loop
My.Settings.Save()
End If
Here is the code.
public static class SettingsUpdate
{
public static void Update()
{
try
{
var a = Assembly.GetExecutingAssembly();
string appVersionString = a.GetName().Version.ToString();
if( UserSettings.Default.internalApplicationVersion != appVersionString )
{
var currentConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );
var exeName = "MyApplication.exe";
var companyFolder = new DirectoryInfo( currentConfig.FilePath ).Parent.Parent.Parent;
FileInfo latestConfig = null;
foreach( var diSubDir in companyFolder.GetDirectories( "*" + exeName + "*", SearchOption.AllDirectories ) )
{
foreach( var file in diSubDir.GetFiles( "user.config", SearchOption.AllDirectories ) )
{
if( latestConfig == null || file.LastWriteTime > latestConfig.LastWriteTime )
{
latestConfig = file;
}
}
}
if( latestConfig != null )
{
var lastestConfigDirectoryName = Path.GetFileName( Path.GetDirectoryName( latestConfig.FullName ) );
var latestVersion = new Version( lastestConfigDirectoryName );
var lastFramework35Version = new Version( "4.0.4605.25401" );
if( latestVersion <= lastFramework35Version )
{
var destinationFile = Path.GetDirectoryName( Path.GetDirectoryName( currentConfig.FilePath ) );
destinationFile = Path.Combine( destinationFile, lastestConfigDirectoryName );
if( !Directory.Exists( destinationFile ) )
{
Directory.CreateDirectory( destinationFile );
}
destinationFile = Path.Combine( destinationFile, latestConfig.Name );
File.Copy( latestConfig.FullName, destinationFile );
}
}
Properties.Settings.Default.Upgrade();
UserSettings.Default.Upgrade();
UserSettings.Default.internalApplicationVersion = appVersionString;
UserSettings.Default.Save();
}
}
catch( Exception ex )
{
LogManager.WriteExceptionReport( ex );
}
}
}
May this will help you :)
When Settings1.Upgrade() doesn't work as you espected, may try to delete previous user config files and try again.
In my case, Release and Debug versions are not correlative, then upgrade seems to fails because there is a conflict between versions in same directory related to debug/release outputs.
Clearing all previous user config files (appdata\local....) seems to solve the problem, calling Upgrade() works and the workaround proposed here works.
I hope it works for you.
精彩评论