加载 .NET WinForm 应用程序 user.config 文件时如何捕获异常?

Posted

技术标签:

【中文标题】加载 .NET WinForm 应用程序 user.config 文件时如何捕获异常?【英文标题】:How to catch exception when loading .NET WinForm app user.config file? 【发布时间】:2011-03-05 12:57:08 【问题描述】:

有时在使用默认配置系统的 .NET (2.0) WinForm 桌面应用程序中,user.config 文件会损坏并且无法再加载(当配置系统尝试加载它时,它会抛出一个System.Xml.XmlException)。

抛开“为什么文件首先损坏”的问题(可能是宇宙射线,或硬盘问题,或其他您无法控制的问题),问题就变成了“如何捕获这个异常并用它做一些有意义的事情?

Microsoft's Connect site has a report on this sort of problem。不幸的是,他们的报告不是很有帮助。

是否可以捕获源自默认配置系统加载程序本身的异常?或者您是否必须推出自己的配置系统才能捕获此类异常?

【问题讨论】:

文件损坏时要考虑的一个地方是防病毒检查程序,当我发现一个众所周知的 AV 有时会在 VC++ 6 编译它们时完全删除源代码文件的那一天是我开始的那一天对他们感到偏执:)。 @ho1 - 是的,我也有这个想法。由于这种情况很少发生,而且我无法重现它,所以我的怀疑程度很高,我考虑过 AV、过热的反恶意软件应用程序、病毒,甚至是宇宙射线! 【参考方案1】:

一种简单的方法是拥有一个“加载器”应用程序,它所做的只是检查真实应用程序的配置文件是否存在,否则创建它,然后启动真实应用程序。

可能是一些我不知道的更简洁的方法。

【讨论】:

加载应用程序无法获取另一个应用程序的 user.config 文件的位置 - 它只能找到自己的 user.config 文件。 @Keithius:嗯,是的,不是的,它不能自动找到其他应用程序的 .config 文件,但要成为一个加载器应用程序,它需要被告知它要加载的应用程序在哪里,如果它知道应用程序在哪里,它可能会找到该应用程序的 .config 文件... 可能,但可能不是,因为应用程序的 user.config 文件的默认位置是:\\__\\user.config - 您无法(可靠地)自行确定的是 位。 @Keithius:我的错误是在考虑 app.config 文件。但即便如此,您也可以通过各种方式在用户目录中搜索它。也许您也可以使用Configuration.LocationsConfigurationManager.OpenExeConfiguration 来找到它?从未做过,但听起来很有可能。【参考方案2】:

出了点问题——可能是您的应用程序正在编写一个空白的 user.config 文件。这是一个需要调查和修复的错误。可能是您的应用程序没有干净地退出(所以它有时会默默地擦除 app.config,所以我先看看关闭顺序。此外,在文件上粘贴第 3 方文件实用程序可能会对您有所帮助准确地看到它何时何地被破坏)。

如果您无法解决问题,那么我能想到的最佳解决方法是使用独立的 XML 配置文件(放弃自动 app.config 方法)——然后您可以完全控制加载的时间和位置并保存。

但是,从根本上说,存在很大的代码异味,我想知道为什么标准的 xml 配置方法在我的应用程序中运行良好,而它在成千上万的其他应用程序中运行良好。

【讨论】:

我试图找出 为什么 user.config 文件已损坏,但这是一个非常罕见的错误(我可以'不在受控条件下繁殖)。如果是关机问题,则可能是意外关机 - 可能在应用程序关闭时计算机正在关闭(例如,从墙上拔下插头)。即使我推出了自己的配置系统,我仍然无法阻止这样的事情发生。假设我无法阻止它发生,我能做的最好的事情就是在它发生时尝试在运行时修复它。【参考方案3】:

原来你可以捕捉到这个异常。我需要的提示来自这个问题:

C# - User Settings broken

就我而言,(WinForms 应用程序),我在父(启动)表单中的异常处理程序会捕获此异常。但我想你也可以在ApplicationEvents 中使用MyApplication_UnhandledException 处理程序。底线是,您需要某种高级别的“未处理异常”处理程序来捕获它。

此外,您可以查看异常的 InnerException 并查看它是否属于 System.Configuration.ConfigurationErrorsException 类型。如果是,那么您可以查看此 InnerException 的 .FileName 属性以获取 user.config 文件的完整文件名。

一旦你有了这个,你可以做点什么 - 尝试检查它的内容,看看它有什么问题,或者(最坏的情况)删除它并重新启动应用程序,以便使用所有默认设置重新创建它。

正如我之前所说,这是一个非常罕见的异常,可能是由突然的系统关闭或其他无法控制的事件(例如断电)引起的。不过,很高兴终于能够做点什么

【讨论】:

【参考方案4】:
[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();
    

【讨论】:

【参考方案5】:

我遇到了同样的问题。框架中一定有错误,因为没有其他人写入文件。 我创建了一个可以解决大部分问题的小类。

您唯一需要做的就是在程序开始时调用 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;
    

【讨论】:

以上是关于加载 .NET WinForm 应用程序 user.config 文件时如何捕获异常?的主要内容,如果未能解决你的问题,请参考以下文章

Winform下pictruebox控件加载网络图片

winform wpf 同时使用log4net出错处理

.net winform 高手教教我!谢谢了

Winform是啥?????

C# winform开发嵌套Chrome内核浏览器(WebKit.net)开发

Winform VS WPF?