问题描述
我正在使用 CustomSettingProvider,可以在这里找到:http://www.codeproject.com/KB/vb/CustomSettingsProvider.aspx
I'm using the CustomSettingProvider as can be found here : http://www.codeproject.com/KB/vb/CustomSettingsProvider.aspx
在某些机器上,抛出空引用异常:
On some machines, a null reference exception is thrown :
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 方法..
cx.a() is either the getvalue or setvalue method ..
有什么想法吗?
......... 编辑 .....
........... EDIT ...............................
此 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;
}
}
推荐答案
问题原因:
一些机器名称以数字开头.IE.965GDF5".不过,XML 标签不能以数字开头,因此会出现所有错误.
some machine names start with numbers. ie. "965GDF5". XML Tags cannot start with numbers though, hence all the errors.
这篇关于仅在某些机器上的 CustomSettingProvider 中的 null 引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!