Как перехватить исключение при загрузке файла user.config приложения .NET WinForm? - PullRequest
5 голосов
/ 18 июня 2010

Иногда в .NET (2.0) настольных приложениях WinForm, которые используют систему конфигурации по умолчанию, файл user.config будет поврежден и больше не сможет быть загружен (когда система конфигурации попытается загрузить его, он выдастSystem.Xml.XmlException).

Оставляя в стороне вопрос «почему файл был поврежден в первую очередь» (возможно, это были космические лучи, или проблемы с жесткими дисками, или что-то еще, что вы не можете контролировать),Тогда возникает вопрос: «Как можно поймать это исключение и сделать с ним что-то осмысленное?

На сайте Microsoft Connect есть отчет по этой проблеме . К сожалению, их отчет не очень полезен.

Можно ли перехватывать исключения, возникающие в самом загрузчике системы конфигурации по умолчанию? Или вам придется развернуть свою собственную систему конфигурации, чтобы иметь возможность перехватывать исключения такого типа?

Ответы [ 5 ]

1 голос
/ 26 сентября 2013

У меня была такая же проблема.В Framework должна быть ошибка, потому что никто больше не пишет файл.Я создал небольшой класс, который может излечить большинство проблем.

Единственное, что вам нужно сделать, это вызвать HealUserSettings в начале вашей программы и вызвать BackupUserSettings при сохранении настроек.Если хотите, вы можете удалить окно сообщений, информирующее вашего пользователя о том, что все его настройки потеряны.

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;
    }
}
1 голос
/ 20 августа 2011

Оказывается, вы можете поймать это исключение.Подсказка, в которой я нуждался, исходила от этого вопроса:

C # - пользовательские настройки нарушены

В моем случае (приложение WinForms) обработчик исключений, который есть в моем родителе (форма автозапуска ловит это исключение.Но я полагаю, вы можете использовать обработчик MyApplication_UnhandledException в ApplicationEvents.Суть в том, что вам нужен какой-то высокоуровневый обработчик «необработанного исключения», чтобы перехватить это.

Кроме того, вы можете посмотреть на исключение InnerException и посмотреть, имеет ли оно тип System.Configuration.ConfigurationErrorsException.Если это так, то вы можете просмотреть свойство .FileName этого InnerException, чтобы получить полное имя файла user.config.

Как только вы это сделаете, вы можете что-то с этим сделать - попробуйте проверить его содержимое, чтобы увидеть, что с ним не так, или (в худшем случае) удалить его и перезапустить приложение, чтобы оно было создано заново со всеминастройки по умолчанию.

Как я уже говорил, это очень редкое исключение, вероятно, вызванное внезапным отключением системы или другими неконтролируемыми событиями (например, отключением питания).Тем не менее, приятно наконец иметь возможность сделать что-то с этим.

0 голосов
/ 21 сентября 2011
[STAThread]
private static void Main(string[] args)
{
    try
    {
        // ...
    }
    catch (System.Configuration.ConfigurationErrorsException ex)
    {   
        var config = ((System.Configuration.ConfigurationErrorsException)ex.InnerException).Filename;
        // notify user, ask them to restart
        System.IO.File.Delete(config);
        Application.Exit();
    }
}
0 голосов
/ 18 июня 2010

Что-то не так - что-то, вероятно, ваше приложение пишет пустой файл user.config.Это ошибка, которую нужно исследовать и исправить.Может случиться так, что ваше приложение не завершается корректно (поэтому иногда оно молча стирает app.config, поэтому я бы начал с рассмотрения последовательности выключения. Кроме того, использование сторонней файловой утилиты для файла может помочь вампоймать, увидеть точно, когда и где он поврежден).

Если вы не можете решить проблему, то лучший обходной путь, который я могу придумать, - это использовать независимый файл конфигурации XML (отказ от автоматизированного подхода app.config).) - тогда у вас есть полный контроль над тем, когда и где он загружается и сохраняется.

Но, по сути, есть большой запах кода, и я хотел бы знать, почему стандартный подход к конфигурации XML не работает вмое приложение, когда оно отлично работает в тысячах других.

0 голосов
/ 18 июня 2010

Одним простым способом было бы иметь приложение-загрузчик, которое все, что оно делает, это проверяет, существует ли файл конфигурации для реального приложения, в противном случае создайте его и затем запустите настоящее приложение.какой-то более аккуратный способ сделать это, о котором я не знаю.

...