سؤال

كان لدينا استثناء نادر عند قراءة إعدادات مستخدم .NET القياسية (هذه هي تلك الموجودة في "خصائص المشروع" في 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: 

*ملاحظة: يتم إعادة إنشاء هذا من تطبيق اختبار.

لقد قمت بسحب ملف user.config ، وكان نصفه مفقودًا.

أتوقع إنهاء تطبيقنا فجأة لسبب أو لآخر.

هذا يبدو نادرًا جدًا ، إليك كيفية تفاعلنا مع الإعدادات:

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

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

هل هناك أي خطأ في كيفية استخدامنا؟ كلا المكالمتين لديهما تجربة تجرب تضع بعض القيم الافتراضية ، ولكن يجب أن تكون القيم قادرة على إعادة التعيين من تطبيقنا.

عندما في هذه الحالة ، لا يمكن لتطبيقنا حفظ إعدادات جديدة-ولا يمكنني معرفة طريقة جيدة للتعافي برمجيًا. اضطررت إلى العثور يدويًا على user.config وحذفه.

لقد حاولت أيضًا استدعاء الإعدادات. Reset () ، وما إلى ذلك ، لكن أحصل على نفس الاستثناء.

أي أفكار حول كيفية إصلاح هذا؟ أم أننا أفضل حالًا في كتابة نظام الإعدادات الخاصة بنا أو توفير الإعدادات المستمرة بطريقة أخرى؟

تعديل: يتمثل الحل البديل في حذف الملف من الكود ، إذا حصلت على configurationRrosexception.

هل يعرف أي شخص كيفية الحصول على المسار الكامل لملف user.config؟

هل كانت مفيدة؟

المحلول

تتمثل طريقة الاسترداد برمجياً في القيام بما فعلته يدويًا - احذف ملف إعدادات المستخدم. ثم يتصل Settings.Reset. (يمكنك أيضًا كتابة ملف إعدادات مستخدم جديد مع قيم افتراضية بدلاً من حذفه ، ولكن إذا كنت تستخدم مدير التكوين بشكل صحيح ، فهذا نفس الشيء.)

هذا أمر نادر الحدوث ، لكنه لم يسمع به تمامًا. لا يمكن فقط تعطل البرنامج أثناء كتابة ملف إعدادات المستخدم ، فالملف نفسه قابل للكشف عن المستخدم ، لذلك يمكن للبرامج الأخرى التي يقوم بها المستخدم العبث بها.

لتجنب هذا الضعف المحدد ، استمر في إعدادات المستخدم في متجر متين مع سلامة المعاملات ، أي قاعدة بيانات. (لا يزال لديك نقاط ضعف ، وليس هذا فقط.) هذا كثير من العمل لما سيكون في معظم الحالات تحسنا هامشيًا في الموثوقية. لكن "في معظم الحالات" لا يعني "في جميع الحالات ؛" لك قد تستدعي ذلك.

نصائح أخرى

إليك الحل لا يتطلب منك الخروج من التطبيق مع مجد إلى Jarle (http://www.codeproject.com/articles/30216/handling-corrupt-user-config-settings؟msg=3608682#xx3608682xx). في وقت مبكر ، قبل أن يتم استدعاء الإعدادات ، استخدم هذا

    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;
    }

في الأساس ، بدلاً من الاعتماد على الجلسات لرمي الخطأ ، اقرأ الملف مع ConfigurationManager ، وبهذه الطريقة لا تدخل إصدار النظام في حالة سيئة.

[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();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top