Пустая ссылка в CustomSettingProvider только на некоторых машинах

Я использую CustomSettingProvider, который можно найти здесь: http://www.codeproject.com/KB/vb/CustomSettingsProvider.aspx

На некоторых машинах выдается исключение нулевой ссылки:

System.NullReferenceException: .

   bij cx.a(SettingsPropertyValue A_0)
   bij cx.a(SettingsContext A_0, SettingsPropertyValueCollection A_1)
   bij System.Configuration.SettingsBase.SaveCore()
   bij System.Configuration.SettingsBase.Save()
   bij System.Configuration.ApplicationSettingsBase.Save()

cx.a () является либо методом getvalue, либо setvalue.

Есть идеи?

........... РЕДАКТИРОВАТЬ...............................

Этот метод GetValue возвращает XPathException: выражение должно вычисляться как набор узлов при выполнении (метод SelectSingleNode)

    private string GetValue(SettingsProperty setting)
    {
        string ret = "";
        if (setting == null)
            return "";

        try
        {
            //Try to read setting ??
            XmlNode foundNode = null;
            string nodeSelectStr = SETTINGSROOT + "/" + SystemInformation.ComputerName + "/" + setting.Name;
            if (IsRoaming(setting))
            {
                nodeSelectStr = SETTINGSROOT + "/" + setting.Name;
            }

            foundNode = SettingsXML.SelectSingleNode(nodeSelectStr);
            if (foundNode != null)
            {
                ret = foundNode.InnerText;
            }
            else //Not found .. ?
            { 
                if ((setting.DefaultValue != null))
                {
                    ret = setting.DefaultValue.ToString();
                }
                else
                {
                    ret = "";
                }
            }
        }
        catch (Exception exc)
        {
            Errors.CatchError("ErrorHintObjectOrAction", exc);
        }

        return ret;
    }











public class CustomSettingProvider : SettingsProvider
{

    //XML Root Node
    const string SETTINGSROOT = "Settings";

    public override void Initialize(string name, NameValueCollection col)
    {
        base.Initialize(this.ApplicationName, col);
    }

    public override string ApplicationName
    {
        get
        {
            if (Application.ProductName.Trim().Length > 0)
            {
                return Application.ProductName;
            }
            else
            {
                FileInfo fi = new FileInfo(Application.ExecutablePath);
                return fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length);
            }
        }
        //Do nothing
        set { }
    }

    public virtual string GetAppSettingsPath()
    {
        return ApplicatiePaths.SettingsPath;
        //Used to determine where to store the settings
        //System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath);
        //return fi.DirectoryName;
    }

    public virtual string GetAppSettingsFilename()
    {
        //Used to determine the filename to store the settings
        return ApplicationName + ".settings";
    }

    public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
    {
        //Iterate through the settings to be stored
        //Only dirty settings are included in propvals, and only ones relevant to this provider
        foreach (SettingsPropertyValue propval in propvals)
        {
            SetValue(propval);
        }

        try
        {
            SettingsXML.Save(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename()));
        }
        catch (Exception ex)
        {
            //Ignore if cant save, device been ejected
        }
    }

    public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props)
    {
        //Create new collection of values
        SettingsPropertyValueCollection values = new SettingsPropertyValueCollection();

        //Iterate through the settings to be retrieved

        foreach (SettingsProperty setting in props)
        {
            SettingsPropertyValue value = new SettingsPropertyValue(setting);
            value.IsDirty = false;
            value.SerializedValue = GetValue(setting);
            values.Add(value);
        }
        return values;
    }


    private XmlDocument m_SettingsXML = null;
    private XmlDocument SettingsXML
    {
        get
        {
            //If we dont hold an xml document, try opening one.  
            //If it doesnt exist then create a new one ready.
            if (m_SettingsXML == null)
            {
                m_SettingsXML = new XmlDocument();

                try
                {
                    m_SettingsXML.Load(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename()));
                }
                catch (Exception ex)
                {
                    //Create new document
                    XmlDeclaration dec = m_SettingsXML.CreateXmlDeclaration("1.0", "utf-8", string.Empty);
                    m_SettingsXML.AppendChild(dec);

                    XmlNode nodeRoot = null;

                    nodeRoot = m_SettingsXML.CreateNode(XmlNodeType.Element, SETTINGSROOT, "");
                    m_SettingsXML.AppendChild(nodeRoot);
                }
            }

            return m_SettingsXML;
        }
    }

    private string GetValue(SettingsProperty setting)
    {
        string ret = "";

        //This method is throwing the null reference exception, 
        //so 'setting' has got to be null ??

        try
        {
            if (IsRoaming(setting))
            {
                ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + setting.Name).InnerText;
            }
            else
            {
                ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + SystemInformation.ComputerName  + "/" + setting.Name).InnerText;
            }

        }
        catch (Exception ex)
        {
            if ((setting.DefaultValue != null))
            {
                ret = setting.DefaultValue.ToString();
            }
            else
            {
                ret = "";
            }
        }

        return ret;
    }


    private void SetValue(SettingsPropertyValue propVal)
    {
        XmlElement MachineNode = default(XmlElement);
        XmlElement SettingNode = default(XmlElement);

        //Determine if the setting is roaming.
        //If roaming then the value is stored as an element under the root
        //Otherwise it is stored under a machine name node 
        try
        {
            if (IsRoaming(propVal.Property))
            {
                SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + propVal.Name);
            }
            else
            {
                SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + SystemInformation.ComputerName + "/" + propVal.Name);
            }
        }
        catch (Exception ex)
        {
            SettingNode = null;
        }

        //Check to see if the node exists, if so then set its new value
        if ((SettingNode != null))
        {
            SettingNode.InnerText = propVal.SerializedValue.ToString();
        }
        else
        {
            if (IsRoaming(propVal.Property))
            {
                //Store the value as an element of the Settings Root Node
                SettingNode = SettingsXML.CreateElement(propVal.Name);
                SettingNode.InnerText = propVal.SerializedValue.ToString();
                SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(SettingNode);
            }
            else
            {
                //Its machine specific, store as an element of the machine name node,
                //creating a new machine name node if one doesnt exist.
                try
                {
                    MachineNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + SystemInformation.ComputerName);
                }
                catch (Exception ex)
                {
                    MachineNode = SettingsXML.CreateElement(SystemInformation.ComputerName);
                    SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode);
                }

                if (MachineNode == null)
                {
                    MachineNode = SettingsXML.CreateElement(SystemInformation.ComputerName);
                    SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode);
                }

                SettingNode = SettingsXML.CreateElement(propVal.Name);
                SettingNode.InnerText = propVal.SerializedValue.ToString();
                MachineNode.AppendChild(SettingNode);
            }
        }
    }

    private bool IsRoaming(SettingsProperty prop)
    {
        //Determine if the setting is marked as Roaming
        foreach (DictionaryEntry d in prop.Attributes)
        {
            Attribute a = (Attribute)d.Value;
            if (a is System.Configuration.SettingsManageabilityAttribute)
            {
                return true;
            }
        }
        return false;
    }

}

2 ответа

Решение

Причина проблем:

некоторые имена машин начинаются с цифр. то есть. "965GDF5". XML-теги не могут начинаться с цифр, следовательно, все ошибки.

Я заметил, что у вас есть несколько catch (Exception ex)

Это будет затруднять, потому что вы глотаете вероятную причину проблемы.

Вы, вероятно, должны удалить их, а затем посмотреть, какое исключение выдается. Перехватывать исключения можно только в том случае, если есть исключение, с которым вы можете что-то сделать (преобразование нулевого значения в значение по умолчанию). И даже тогда это должно быть конкретное исключение, а не System.Exception

Другие вопросы по тегам