Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ApplicationSettingsBase.Upgrade() Not Upgrading User Settings after Recompiling with .NET 4.0

Tags:

c#

.net

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

like image 565
Mageuzi Avatar asked Apr 27 '10 14:04

Mageuzi


2 Answers

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 :)

like image 20
Igor Shakola Avatar answered Oct 25 '22 15:10

Igor Shakola


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
like image 121
Richard Lailey Avatar answered Oct 25 '22 14:10

Richard Lailey