关于本站
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 回复