Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch exception when loading .NET WinForm app user.config file?

Sometimes in .NET (2.0) WinForm desktop apps which use the default configuration system, the user.config file will become corrupted and can't be loaded anymore (when the configuration system tries to load it, it'll throw a System.Xml.XmlException).

Putting aside the question of "why did the file get corrupted in the first place" (maybe it was cosmic rays, or HDD problems, or something else you can't control), the question then becomes "how can one catch this exception and do something meaningful with it?

Microsoft's Connect site has a report on this sort of problem. Unfortunately, their report isn't very helpful.

Is it possible to catch exceptions that originate in the default configuration system loader itself? Or would you have to roll your own configuration system to be able to catch this type of exception?

like image 739
Keithius Avatar asked Nov 05 '22 12:11

Keithius


2 Answers

Turns out you can catch this exception. The hint I needed came from this question:

C# - User Settings broken

In my case, (WinForms app), the exception handler I have in my parent (startup) form catches this exception. But I suppose you could use the MyApplication_UnhandledException handler in ApplicationEvents as well. Bottom line is, you need some sort of high-level "unhandled exception" handler to catch this.

Additionally, you can look at the exception's InnerException and see if it is of type System.Configuration.ConfigurationErrorsException. If it is, then you can look at the .FileName property of this InnerException to get the full file name of the user.config file.

Once you have this, you can do something about it - try to check its contents to see what's wrong with it, or (worst case) delete it and restart the app so it is re-created with all the default settings.

As I said before, this is a very rare exception, probably caused by sudden system shutdowns or other uncontrollable events (e.g., power outage). Nevertheless, it is nice to finally be able to do something about it.

like image 166
Keithius Avatar answered Nov 15 '22 07:11

Keithius


I had the same problem. There has to be an error in the Framework, because no one else writes the file. I created a little class that can heal most of the problems.

The only thing you have to do is to call HealUserSettings at the start of your program and call BackupUserSettings when saving your settings.

If you like you can eliminate the Messagebox that informs your user that all his settings are lost.

public static class SettingsFileRecovery
{
    public static void HealUserSettings()
    {
        string file;
        try
        {
            file = GetUserSettingsFile();
        }
        catch (ConfigurationException ex)
        {
            file = ex.Filename;
            if (File.Exists(file))
            {
                if (!RestoreUserSettings(file))
                {
                    MessageBox.Show("Settings are lost.", "Error", MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);

                    // must delete wrong file
                    File.Delete(file);
                }
                Application.Restart();
            }
        }

        // does not exist
        if (!File.Exists(file))
        {
            if (RestoreUserSettings(file))
            {
                Application.Restart();
            }
        }


    }

    public static string GetUserSettingsFile()
    {
        Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
        return config.FilePath;
    }

    public static string GetBackupFile(string file)
    {
        return file + ".bak";
    }

    public static void BackupUserSettings()
    {
        try
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            config.SaveAs(GetBackupFile(config.FilePath));
        }
        catch (Exception)
        {
            // file is corrupt but no problem because no backup is written
        }
    }

    public static bool RestoreUserSettings(string file)
    {
        string backupFile = GetBackupFile(file);
        if (File.Exists(backupFile))
        {
            File.Copy(backupFile, file, true);
            return true;
        }
        return false;
    }
}
like image 36
Uwe Wittig Avatar answered Nov 15 '22 05:11

Uwe Wittig