开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜