Domanda

Abbiamo avuto una rara eccezione si verifica quando la lettura delle impostazioni utente .Net normali (questo sono quelle che si trovano in "proprietà di progetto" in VS 2008):

System.Configuration.ConfigurationErrorsException was caught
  Message="Configuration system failed to initialize"
  Source="System.Configuration"
  BareMessage="Configuration system failed to initialize"
  Line=0
  StackTrace:
       at System.Configuration.ConfigurationManager.PrepareConfigSystem()
       at System.Configuration.ConfigurationManager.GetSection(String sectionName)
       at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
       at System.Diagnostics.DiagnosticsConfiguration.GetConfigSection()
       at System.Diagnostics.DiagnosticsConfiguration.Initialize()
       at System.Diagnostics.DiagnosticsConfiguration.get_IndentSize()
       at System.Diagnostics.TraceInternal.InitializeSettings()
       at System.Diagnostics.TraceInternal.get_Listeners()
  InnerException: System.Configuration.ConfigurationErrorsException
       Message="Unexpected end of file has occurred. The following elements are not closed: setting, SettingsTest.Properties.Settings, userSettings, configuration. Line 7, position 1. (C:\\Documents and Settings\\USER\\Local Settings\\Application Data\\Hitcents\\SettingsTest.vshost.exe_Url_ghwhc20utv4toanuinmj0pfsljthcugo\\1.0.0.0\\user.config line 7)"
       Source="System.Configuration"
       BareMessage="Unexpected end of file has occurred. The following elements are not closed: setting, SettingsTest.Properties.Settings, userSettings, configuration. Line 7, position 1."
       Filename="C:\\Documents and Settings\\USER\\Local Settings\\Application Data\\Hitcents\\SettingsTest.vshost.exe_Url_ghwhc20utv4toanuinmj0pfsljthcugo\\1.0.0.0\\user.config"
       Line=7
       StackTrace:
            at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
            at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
            at System.Configuration.BaseConfigurationRecord.ThrowIfInitErrors()
            at System.Configuration.ClientConfigurationSystem.OnConfigRemoved(Object sender, InternalConfigEventArgs e)
       InnerException: System.Xml.XmlException
            Message="Unexpected end of file has occurred. The following elements are not closed: setting, SettingsTest.Properties.Settings, userSettings, configuration. Line 7, position 1."
            Source="System.Xml"
            LineNumber=7
            LinePosition=1
            SourceUri=""
            StackTrace:
                 at System.Xml.XmlTextReaderImpl.Throw(Exception e)
                 at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
                 at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res, String arg)
                 at System.Xml.XmlTextReaderImpl.ThrowUnclosedElements()
                 at System.Xml.XmlTextReaderImpl.ParseElementContent()
                 at System.Xml.XmlTextReaderImpl.Read()
                 at System.Xml.XmlTextReader.Read()
                 at System.Xml.XmlTextReaderImpl.Skip()
                 at System.Xml.XmlTextReader.Skip()
                 at System.Configuration.XmlUtil.StrictSkipToNextElement(ExceptionAction action)
                 at System.Configuration.BaseConfigurationRecord.ScanSectionsRecursive(XmlUtil xmlUtil, String parentConfigKey, Boolean inLocation, String locationSubPath, OverrideModeSetting overrideMode, Boolean skipInChildApps)
                 at System.Configuration.BaseConfigurationRecord.ScanSectionsRecursive(XmlUtil xmlUtil, String parentConfigKey, Boolean inLocation, String locationSubPath, OverrideModeSetting overrideMode, Boolean skipInChildApps)
                 at System.Configuration.BaseConfigurationRecord.ScanSections(XmlUtil xmlUtil)
                 at System.Configuration.BaseConfigurationRecord.InitConfigFromFile()
            InnerException: 

* NOTA:. Questo viene ricreato da un applicazione di test

ho tirato sul file user.config, e la metà di esso mancava.

Mi aspetto che la nostra applicazione è stata terminata bruscamente per qualche motivo o un altro.

Questo sembra molto rara, qui è il modo in cui interagiamo con le impostazioni:

//How we read
Settings settings = Settings.Default;
_ourStaticMemberVariable = settings.OurValue;

//How we save
Settings settings = Settings.Default;
settings.OurValue = "Our Value";
settings.Save();

E 'qualcosa che non va come stiamo usando? Entrambe le chiamate hanno un try-catch che pongono alcuni valori di default, ma i valori devono essere in grado di ripristinare dalla nostra applicazione.

In questo stato, la nostra applicazione non può salvare le nuove impostazioni - e non riesco a capire un buon modo per recuperare a livello di codice. Ho dovuto trovare manualmente l'user.config ed eliminarlo.

Inoltre ho provato a chiamare Settings.Reset (), ecc, ma ottenere la stessa eccezione.

Tutte le idee su come risolvere questo problema? O siamo meglio a scrivere il nostro proprio sistema di impostazioni o salvataggio delle impostazioni persistenti in un altro modo?

EDIT:. Una soluzione è quella di eliminare il file dal codice, se si ottiene un ConfigurationErrorsException

Qualcuno sa come ottenere il percorso completo del file user.config?

È stato utile?

Soluzione

Il modo per recuperare a livello di codice è quello di fare quello che hai fatto manualmente - eliminare il file delle impostazioni utente. Poi chiamata Settings.Reset. (Si potrebbe anche scrivere un nuovo file di impostazioni utente con valori di default, invece di eliminarlo, ma se si sta utilizzando il gestore di configurazione correttamente che è essenzialmente la stessa cosa.)

Questo è un evento piuttosto raro, ma non è del tutto inaudito. Non solo può il vostro crash del programma durante la scrittura del file di impostazioni utente, il file stesso è user-scrivibile, così gli altri programmi piste utente può pasticciare con essa.

Per evitare questo particolare vulnerabilità, persistono le impostazioni utente in un negozio di lunga durata con l'integrità delle transazioni, vale a dire un database. (Avrai ancora vulnerabilità, non solo questo.) Questo è un sacco di lavoro per ciò che nella maggior parte dei casi sarà un miglioramento marginale in termini di affidabilità. Ma "nella maggior parte dei casi" non significa "in tutti i casi;" il vostro può giustificarlo.

Altri suggerimenti

Ecco una soluzione che non richiede per chiudere l'applicazione con complimenti a Jarle ( http://www.codeproject.com/Articles/30216/Handling-Corrupt-user-config-Settings?msg=3608682#xx3608682xx ). Nella fase iniziale, prima di Impostazioni mai viene chiamato, utilizzare questo

    public static bool CheckSettings()
    {
        var isReset = false;

        try
        {
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
        }
        catch (ConfigurationErrorsException ex)
        {
            string filename = string.Empty;
            if (!string.IsNullOrEmpty(ex.Filename))
            {
                filename = ex.Filename;
            }
            else
            {
                var innerEx = ex.InnerException as ConfigurationErrorsException;
                if (innerEx != null && !string.IsNullOrEmpty(innerEx.Filename))
                {
                    filename = innerEx.Filename;
                }                   
            }

            if (!string.IsNullOrEmpty(filename))
            {
                if (System.IO.File.Exists(filename))
                {
                    var fileInfo = new System.IO.FileInfo(filename);
                    var watcher
                         = new System.IO.FileSystemWatcher(fileInfo.Directory.FullName, fileInfo.Name);
                    System.IO.File.Delete(filename);
                    isReset = true;
                    if (System.IO.File.Exists(filename))
                    {
                        watcher.WaitForChanged(System.IO.WatcherChangeTypes.Deleted);
                    }
                }
            }
        }

        return isReset;
    }

In sostanza, piuttosto che basarsi su Sedute per lanciare l'errore, leggere il file con il ConfigurationManager, in questo modo la versione del sistema non viene mai in cattivo stato.

[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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top