关于本站
1、基于Django+Bootstrap开发
2、主要发表本人的技术原创博客
3、本站于 2015-12-01 开始建站
继续挖VSTO的坑,再填上。这次挖坑是和读写配置有关。
我们写代码,经常会碰到有些数据或设置需要保存。这类东西下面都统一称为配置。
保存配置、读取配置是一件再平常不过的事情了。
保存配置一般有两种方法:写到注册表和写入到文件。
这里不讲写注册表的方法。原因如下:
1)方法简单。找个读写注册表类即可;
2)垃圾问题。如果数据保存在注册表,容易造成注册表数据过多,产生不必要的垃圾;
3)权限问题。操作一些位置的注册表,需要一定权限。麻烦。
所以,我建议大家将数据保存到文件。
保存配置文件的位置一般选择插件所在的目录。但,问题又来了。
一般我们发布插件给用户使用。用户可能会将插件安装到系统目录,例如program files文件夹。在这些系统目录中,有些电脑操作需要权限。一般程序我们可以要求需要管理员权限运行程序。但这个VSTO开发出来的是插件!插件!插件!
它是依附于Office进程运行。例如我开发一个Excel插件,不是我直接打开这个插件。而是我们打开Excel,Excel发现需要加载这个插件,才去加载插件。除非我们打开Excel时用管理员权限运行。但这种情况是少数。我们要考虑大多数情况。
那么,配置文件保存的路径只能选择其他位置。
这里,我们可以把配置文件保存到“我的文档”中。而“我的文档”的路径可以通过系统环境变量获取得到。如下代码获取:
//获取 我的文档 路径 string strPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments);
当然,你还可以在该目录下建一个目录专门保存本插件相关的数据、文件等。
路径问题解决了,剩下就是如何读写配置文件。
这个问题也不难。你可自行设计配置,如保存成xml、ini、json、txt等等。也可以是一个配置数据类,再序列化和反序列化。
这里建议保存成xml、json格式或配置数据类。因为这些操作较为方便,且结构清晰。
给大家演示xml格式的大致方法。
此处会涉及到xml文件的读写,若不懂该部分的知识,请自行了解。
考虑到一个程序可能需要保存多个配置文件。则创建一个配置操作的基类,命名为ClsBaseConfig。
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; namespace Config { /// <summary> /// 配置读写基类 /// </summary> public class ClsBaseConfig { #region 属性 protected string ConfigName { get; set; } //配置文件名(要包含后缀名) protected string ConfigPath { get; set; } //配置文件的路径 protected string RootNodeName { get; set; } //配置文件根节点名 //当前程序配置文件路径 protected string ConfigFullName { get { return Path.Combine(ConfigPath, ConfigName); } } #endregion #region 创建文档和节点 /// <summary> /// 创建Config文件 /// </summary> /// <returns>返回创建是否成功</returns> protected bool CreateConfig() { try { bool blnExists = File.Exists(this.ConfigFullName); if (blnExists) File.Delete(this.ConfigFullName); //若文件存在,则删除 //创建配置文件 XmlDocument xmlDoc = new XmlDocument(); //创建类型声明节点 XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", ""); xmlDoc.AppendChild(node); //创建根节点 XmlNode root = xmlDoc.CreateElement(RootNodeName); xmlDoc.AppendChild(root); //保存xml文件 xmlDoc.Save(this.ConfigFullName); //销毁资源 root = null; node = null; xmlDoc = null; return true; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "创建配置文件出错"); return false; } } /// <summary> /// 创建子节点 /// </summary> /// <param name="xmlDoc">xml文档</param> /// <param name="parentNode">父节点</param> /// <param name="strName">节点名</param> /// <param name="strValue">值</param> protected void CreateSubNode(XmlDocument xmlDoc, XmlNode parentNode, string strName, string strValue) { XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, strName, null); node.InnerText = strValue; parentNode.AppendChild(node); node = null; } #endregion #region 获取相关Xml对象 /// <summary> /// 获取Xml配置文档 /// </summary> /// <returns>返回Xml配置文档</returns> protected XmlDocument GetDocument() { bool blnExists = File.Exists(this.ConfigFullName);//判断文件是否存在 //不存在则创建 if (!blnExists) { if (!this.CreateConfig()) return null; } XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(this.ConfigFullName); //加载xml文件 return xmlDoc; } /// <summary> /// 获取根节点,若没有则自动创建 /// </summary> /// <param name="xmlDoc">Xml文档</param> /// <returns>返回根节点</returns> protected XmlNode GetRootNode(XmlDocument xmlDoc) { XmlNode xmlRoot = xmlDoc.SelectSingleNode(RootNodeName);//找到根节点 //获取不到,则添加进去 if (xmlRoot == null) { xmlRoot = xmlDoc.CreateElement(RootNodeName); xmlDoc.AppendChild(xmlRoot); } return xmlRoot; } /// <summary> /// 获取节点,若没有则自动创建 /// </summary> /// <param name="xmlDoc">Xml文档</param> /// <param name="xmlParent">父节点</param> /// <param name="strName">节点名</param> /// <returns>返回节点</returns> protected XmlNode GetNode(XmlDocument xmlDoc, XmlNode xmlParent, string strName) { XmlNode xmlNode = xmlParent.SelectSingleNode(strName); //获取不到,则添加进去 if (xmlNode == null) { xmlNode = xmlDoc.CreateElement(strName); xmlParent.AppendChild(xmlNode); } return xmlNode; } #endregion #region 读写方法 /// <summary> /// 读取设置 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="strParent">父节点</param> /// <param name="strName">参数名</param> /// <param name="defaultValue">默认值</param> /// <returns>返回读取结果,没有则返回默认值</returns> public T ReadConfig<T>(string strParent, string strName, T defaultValue) { try { XmlDocument xmlDoc = GetDocument(); //加载xml文件 XmlNode xmlRoot = GetRootNode(xmlDoc); //获取根节点 XmlNode xmlParent = GetNode(xmlDoc, xmlRoot, strParent);//获取父节点 XmlNode xmlNode = GetNode(xmlDoc, xmlParent, strName); //获取该节点 //判断是否有内容 if (xmlNode.InnerText == "") { xmlNode.InnerText = defaultValue.ToString(); xmlDoc.Save(this.ConfigFullName); } //返回内容 string strText = xmlNode.InnerText; xmlNode = null; xmlParent = null; xmlRoot = null; xmlDoc = null; return (T)Convert.ChangeType(strText, typeof(T)); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "写入配置错误"); return defaultValue; } } /// <summary> /// 写入设置 /// </summary> /// <param name="strParent">父节点</param> /// <param name="strName">参数名</param> /// <param name="strValue">参数值</param> /// <returns>返回布尔值,表示是否写入成功</returns> public bool WriteConfig(string strParent, string strName, string strValue) { try { XmlDocument xmlDoc = GetDocument(); //加载xml文件 XmlNode xmlRoot = GetRootNode(xmlDoc); //获取根节点 XmlNode xmlParent = GetNode(xmlDoc, xmlRoot, strParent);//获取父节点 XmlNode xmlNode = GetNode(xmlDoc, xmlParent, strName); //获取该节点 xmlNode.InnerText = strValue; //写值 xmlDoc.Save(this.ConfigFullName); //保存文件 xmlNode = null; xmlParent = null; xmlRoot = null; xmlDoc = null; return true; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message, "读取配置错误"); return false; } } #endregion } }
代码有点多,该类结构如下:
1)属性:保存路径,文件夹名,根节点名
2)xml操作方法
3)配置读写方法
建立基类之后,我们有需要单独保存成一个配置文件的配置,继承该类即可。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.IO; namespace Config { /// <summary> /// 该插件配置文件读写类:读写配置信息 /// </summary> public class ClsThisAddinConfig:ClsBaseConfig { //构造函数 public ClsThisAddinConfig(string strPath) { ConfigPath = strPath; ConfigName = "Config.xml"; RootNodeName = "Config"; } } }
写清配置文件所需的参数即可。
这里我所写的代码都没设定配置数据的名称等。可以在开发的过程中,随意添加配置。
例如,读取配置:
string strPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments); ClsThisAddinConfig clsConfig = new ClsThisAddinConfig(strPath); //从父节点Navgater中读取配置名show为的值,该值为布尔值。默认为true bool oldNavSetting = clsConfig.ReadConfig<bool>("Navgater", "Show", true);
若配置文件该值不存在,则返回默认值。
再如,写入配置:
string strPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments); ClsThisAddinConfig clsConfig = new ClsThisAddinConfig(strPath); //写入父节点Navgater中配置名show的配置项 clsConfig.WriteConfig("Navgater", "Show", true.ToString());
读写配置,就是读写文件。
相关专题: VSTO的那些坑
lizhihua508@qq.com
杨老师写的很好,但我现在需要插件首次启动时即可读取预先写好的初始化文件,而不是启动后生成下次读取,这个该怎么操作呢?
2017-09-28 05:22 回复