config文件的使用

一、缘起

最近做项目开始使用C#,因为以前一直使用的是C++,因此面向对象思想方面的知识还是比较全面的,反而是因没有经过完整、系统的.Net方面知识的系统学习,经常被一些在C#老鸟眼里几乎是常识的小知识点给绊倒。

为什么这么说呢,因为我在网络上查找的资料的时候,经常大部分问题,都是能够找到或多或少的参考资料,但是这些小知识点却很少能够找到正确的解决方法,有也是只有提问,没有回到,那么这种情况出现,就只有2种解释:
1、这个方面的问题很难,难到没有人能够解决;
2、这个问题太简单,简单到稍微熟悉的人都不屑于回答,提问者也在一番思考后,轻松找到答案。(我比较倾向这个,呵呵,因此我也把这些小知识,叫做:容易被忽略的细节)

然而,无论问题是否简单,既然我会被绊倒,耽搁时间,肯定也会有人被同样耽搁,因此我想把这些细节整理出来,还是具有一定意义的。

于是,本系列文章开始...

二、问题描述

除了正常情况下的config文件,使用ConfigurationManager加载,我们还可能会碰到一下这样的情况:
1、加载非当前应用程序yyy.exe默认的config文件的xxx.exe.config文件;(比如:与yyy.exe.config不在同一目录下 或者 文件名不同)
2、加载非应用程序的xxx.config文件;
3、让类库xxx.dll内的函数读取默认config文件的时候,读取的是xxx.dll同级目录下的xxx.dll.config文件,而不是加载xxx.dll的应用程序yyy.exe的默认应用程序配置文件:yyy.exe.config;
    以上三种情况,都不能直接使用ConfigurationManager来加载

三、解决过程

让我们从最基础、最简单、最常见的config文件的加载来入手,解决上面三个问题:

step1:研究基础的config文件加载

config文件,是给客户端应用程序保存配置信息用的,一般情况,一个应用程序只会有一个这样的文件,在编译之前,叫做App.config,每次使用Visual Studio编译,都会Copy到应用程序的生成目录,且Rename为:应用程序名.config。
    要读取config文件内的信息,只需要使用ConfigurationManager的相关函数和属性即可,因此我们来研究下ConfigurationManager,看看是否能找到解决问题的相关信息。
打开MSDN,找到这样一个方法:

OpenExeConfiguration  已重载。 将指定的客户端配置文件作为 Configuration 对象打开。

OK,要找的就是这个,因为这个方法有一个重载方法是:

OpenExeConfiguration(String)  将指定的客户端配置文件作为 Configuration 对象打开。

step2:加载非当前应用程序默认的config文件

于是,第一个问题的解决方案,似乎、应该、可能找到了,按照MSDN上的说明,若我们把要打开的xxx.exe.config的路径作为参数传入即可,代码如下:

Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe.config");
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

但是,事情并没有这么顺利,这样是无法打开xxx.exe.config文件的,经过调试,发现:config的属性FilePath的值为:"C:\\xxx.exe.config.config",程序自己在传入的参数后增加了“.config”作为要打开的config文件的路径,这显然和我们之前从MSDN上所看到的不一样,不用说,我们被微软小小的耍了一把。这里要传入的参数,不应该是要打开的config的路径,而应该是这个config文件对应的应用程序的路径,也就是说上面的代码应该这样写:

Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe"); // 写的是应用程序的路径
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

再次运行,呵呵,还是不行,提示错误:『加载配置文件时出错: 参数“exePath”无效。参数名: exePath』。显然我们有被耍了,这里要传入应用程序路径(exePath)没错,但是因为我们并没有在xxx.exe.config文件同目录下,加入xxx.exe文件,因此我们传入的exePath实际上是无效的,可见为了能够加载xxx.exe.config,我们弄一个xxx.exe文件放在一起。

ok,运行,成功。

小结1:第一个问题的解决方案找到:

使用ConfigurationManager.OpenExeConfiguration(string exePath)即可,同时注意2个小细节:
A:改方法需传入的是exePath,而不是configPath;
B:exePath必须是有效的,因此xxx.exe和xxx.exe.config应该成对出现,缺一不可。

step3:扩展step2的战果,找到加载xxx.config的方法

step2已经找到了加载xxx.exe.config的方法,观察xxx.exe.config的名称,发现,若把xxx.exe看成YYY,显然xxx.exe.config = YYY.config,也就是说:xxx.exe.config是xxx.config中比较特殊的一种,他要求config文件的文件名最后4个字母必须是“.exe”。

此时,大胆推测,使用ConfigurationManager.OpenExeConfiguration(string exePath),应该可以解决问题。

Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx"); // 记得要有xxx文件,否则这个路径就是无效的了。
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

运行,HOHO,成功了。

小结2:第二个问题和第一个问题的解决方案一样。

step4:扩展xxx.config解决问题3

继续扩大战果,还是从文件名上来找思路,我们要加载的xxx.dll.config,其实也是xxx.config中稍微特殊的一种,显然也可以和step3那样处理。

使用OpenExeConfiguration(string exePath)来解决问题三,在dll内,碰到需要读取config文件信息的时候,放弃使用ConfigurationManager的函数或属性直接获取,而改用OpenExeConfiguration(string exePath)加载config文件为一个Configuration对象的对应函数或属性即可。

小结3:第三个问题同样可以按照第一个问题的方案来做。

四、额外的思考

在应用程序yyy.exe中通过ConfigurationManager可以很方便的读取到yyy.exe.config文件中的信息,但在类库中使用ConfigruationManager读取的却不是自动编译生成的xxx.dll.cofig文件,而是引用类库的应用程序yyy.exe的yyy.exe.config文件。

有没有什么办法,让类库中的ConfigurationManager读取的也是他默认的xxx.dll.config文件呢?

其实,是可以的,不过这里涉及到了应用程序域(AppDomain)的概念, .Net上的应用程序都是运行在一个应用程序域(AppDomain)内的,在程序启动之初,都会默认启动一个AppDomain,查看MSDN可以看到AppDomain有一个属性:SetupInformation,这个属性保存的就是当前域的config文件路径;可惜,这个属性是只读的,所以我们默认AppDomain的config文件路径。

因此,若想让类库能够直接使用ConfigurationManager来读取自己默认的config文件,就只能把类库放在一个新的AppDomain中执行,并且在创建AppDomain的时候指定他的SetupInformation为类库默认的config文件路径;AppDomain有一个用来创建新AppDomain的方法:CreateDomain(String, Evidence, AppDomainSetup);只要把第三个参数的属性ConfigurationFile只想类库默认的config文件路径即可。

五、附录:实例代码: 代码下载

出处:https://www.cnblogs.com/bearhand/archive/2008/09/07/1279087.html

=================================================================

通过程序修改Config文件

对于config文件,一般情况下都是使用ConfigurationManager加载,然后通过读取相应节点的值来获取想要的数据,但是,有时候需要修改config文件的值,这时候就用到了OpenExeConfiguration()方法。

MSDN上面对该方法的解释:ConfigurationManager.OpenExeConfiguration方法用来把指定的客户端配置文件作为Configuration对象打开,该方法具有两个重载:

名称 说明
ConfigurationManager.OpenExeConfiguration (ConfigurationUserLevel) 将当前应用程序的配置文件作为 Configuration 对象打开。
ConfigurationManager.OpenExeConfiguration (String) 将指定的客户端配置文件作为 Configuration 对象打开。

一、使用OpenExeConfiguration(ConfigurationUserLevel)重载设置当前应用程序的配置文件

客户端应用程序使用应用于所有用户的全局配置、应用于单个用户的单独配置以及应用于漫游用户的配置。userLevel 参数通过指示该配置文件是不具有用户级别(配置文件与应用程序位于同一目录中),还是具有一个依每个用户而定的用户级别(配置文件位于用户级别所确定的应用程序设置路径中),从而确定所打开的配置文件的位置。

通过向 userLevel 传递下列值之一来指定要获取的配置:

  • 若要获取应用于所有用户的 Configuration 对象,请将 userLevel 设置为 None。

  • 若要获取应用于当前用户的本地 Configuration 对象,请将 userLevel 设置为 PerUserRoamingAndLocal。

  • 若要获取应用于当前用户的漫游 Configuration 对象,请将 userLevel 设置为 PerUserRoaming。

注意:若要获取资源的 Configuration 对象,您的代码必须对它从中继承设置的所有配置文件具有“读取”特权。若要更新配置文件,您的代码还必须对该配置文件及其所在目录具有“写入”特权。

示例程序:

1、配置文件结构如下:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <appSettings>
 4     <add key="ApServer1" value="ApServer1"/>
 5     <add key="ApServer2" value="ApServer2"/>
 6     <add key="LocalHost1" value="LocalHost1"/>
 7     <add key="LocalHost2" value="LocalHost2"/>
 8     <add key="addr" value="11111"/>
 9   </appSettings>
10     <startup>
11         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
12     </startup>
13 </configuration>

2、通过程序修改LocalHost1节点的值

 string strLocalHost1Value1 = ConfigurationManager.AppSettings["LocalHost1"].ToString(); //strLocalHost1Value1="LocalHost1";
//Configuration对象
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["LocalHost1"].Value = "http://127.0.0.1";//保存配置文件
config.AppSettings.SectionInformation.ForceSave = true;
config.Save(ConfigurationSaveMode.Modified);
//重新加载改变的节点
ConfigurationManager.RefreshSection("appSettings");//读取配置文件的值
string strLocalHost1Value2 = ConfigurationManager.AppSettings["LocalHost1"].ToString();//strLocalHost1Value2="http://127.0.0.1"

二、使用OpenExeConfiguration(String)重载设置指定的客户端配置文件

重载指定的客户端config文件主要包括下面3种情况:

1、加载非当前应用程序yyy.exe默认的config文件的xxx.exe.config文件(yyy.exe是当前应用程序,xxx.exe.config与yyy.exe.config文件不在同一目录下)。

2、加载非应用程序的xxx.config文件。

3、让类库xxx.dll内的函数读取默认config文件的时候,读取的是xxx.dll同级目录下的xxx.dll.config文件,而不是加载xxx.dll的应用程序yyy.exe的默认应用程序配置文件:yyy.exe.config。

注意:在类库中使用ConfigruationManager读取的不是自动编译生成的xxx.dll.config文件,而是引用类库的应用程序yyy.exe的yyy.exe.config文件。

解决方法:

按照MSDN上的说明,我们把要打开的xxx.exe.config的路径作为参数传入,代码如下:

1 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe.config");
2 con.AppSettings.Settings["LocalHost2"].Value = "测试";

但是程序运行的时候报错,经过调试,发现con对象的FilePath属性的值为:C:\Modify.exe.config.config,程序自己在传入的参数后增加了“.config”作为要打开的config文件的路径,因为没有这个文件,所以程序报错。这里要传入的参数,不应该是要打开的config文件的路径,而是这个config文件对应的应用程序的路径,上面的代码应修改为:

1 //参数传的是应用程序的路径
2 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe.");
3 con.AppSettings.Settings["LocalHost2"].Value = "测试";

再次运行程序,还是报错,提示“加载配置文件时出错:参数exePath”无效。这里要传入应用程序的路径(exePath)没错,但是因为在xxx.exe.config文件的同一目录下,没有xxx.exe文件,因此我们传入的exePath实际上是无效的,为了能够加载xxx.exe.config文件,需要在同一目录下增加一个xxx.exe文件。(可以在同一目录下新建一个txt文件,修改名称为xxx,扩展名为.exe,这样就可以加载xxx.exe.config配置文件了)

完整的代码如下:

//参数传的是应用程序的路径
Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe");
con.AppSettings.Settings["LocalHost2"].Value = "测试";
//保存配置文件
con.AppSettings.SectionInformation.ForceSave = true;
con.Save(ConfigurationSaveMode.Modified);
//重新加载改变的节点
ConfigurationManager.RefreshSection("appSettings");//读取修改后的配置文件节点值
string str = con.AppSettings.Settings["LocalHost2"].Value;//str="测试"

注意:

使用ConfigurationManager.OpenExeConfiguration(string exePath)即可,同时注意2个小细节:
A:改方法需传入的是exePath,而不是configPath;
B:exePath必须是有效的,因此xxx.exe和xxx.exe.config应该成对出现,缺一不可。

加载非应用程序的xxx.config文件

在上面的例子中,观察xxx.exe.config文件的名称,发现,若把xxx.exe看成YYY,则xxx.exe.config=YYY.config,也就是说:xxx.exe.config是xxx.config文件的一种特殊形式,所以,可以使用如下的代码加载xx.config文件:

//参数传的是应用程序的路径
Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify");
con.AppSettings.Settings["LocalHost2"].Value = "测试";
//保存配置文件
con.AppSettings.SectionInformation.ForceSave = true;
con.Save(ConfigurationSaveMode.Modified);
//重新加载改变的节点
ConfigurationManager.RefreshSection("appSettings");//读取修改后的配置文件节点值
string str = con.AppSettings.Settings["LocalHost2"].Value;//str="测试"

注意:C:\Modify这个文件必须要有。

加载xxx.dll.config文件:

还是从文件名上来找思路,我们要加载xxx.dll.config文件,可以和加载xxx.config文件一样。在dll内,碰到需要读取config文件信息的时候,放弃使用ConfigurationManager读取节点的值,而是使用OpenExeConfiguration(string exePath)方法加载config文件为一个Configuration对象来使用。

注意:通过程序修改配置文件中节点的值,不会修改.config文件里面的值,更改只是发生在内存中。

出处:http://www.cnblogs.com/dotnet261010/p/6597177.html

==============================================================================================

通过从网上的了解,和学习,我们看到ConfigurationManager.OpenMappedExeConfiguration这个方法可以用于打开指定的配置文件,那么看看我们用它来做一些事情吧,下面看代码:

using System;
using System.Collections.Generic;
using System.Configuration;//必须引用:System.Configuration
using System.Linq;
using System.Text;namespace PVG.Lib.Configs
{public class AppConfigHelper{private Configuration config = null;public Configuration Configuration{get { return config; }set { config = value; }}/// <summary>/// 是否加密连接字符串/// </summary>public bool IsEncryptionConnection { get; set; }/// <summary>/// 默认读取当前应用程序的配置信息/// </summary>public AppConfigHelper(){string startPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + AppDomain.CurrentDomain.SetupInformation.ApplicationName;config = ConfigurationManager.OpenExeConfiguration(startPath);IO.DebuggerHelper.OutputLine(startPath);//输出
        }/// <summary>/// 指定的Config文件的路径/// </summary>/// <param name="configPath"></param>public AppConfigHelper(string configPath){string configFilePath = System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;configFilePath = string.IsNullOrEmpty(configPath) ? configFilePath : configPath;//new ExeConfigurationFileMap();config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = configFilePath }, ConfigurationUserLevel.None, true);IO.DebuggerHelper.OutputLine(configFilePath);//输出
        }public string GetConnectionStrings(string ConnName){//return ConfigurationManager.ConnectionStrings[ConnName].ToString();string res = "";if (config != null && config.ConnectionStrings.ConnectionStrings[ConnName] != null)res = config.ConnectionStrings.ConnectionStrings[ConnName].ConnectionString;return res;}public string SetConnectionStrings(string ConnName, string ConnValue){return SetConnectionStrings(ConnName, ConnValue, "");}public string SetConnectionStrings(string ConnName, string ConnValue, string providerName){if (config != null){if (config.ConnectionStrings.ConnectionStrings[ConnName] != null)config.ConnectionStrings.ConnectionStrings[ConnName].ConnectionString = ConnValue;elseconfig.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings(ConnName, ConnValue, providerName));config.Save(ConfigurationSaveMode.Modified);}if (IsEncryptionConnection)encryptionConn();return GetConnectionStrings(ConnName);}public string GetAppSettings(string keyName){string res = "";if (config != null && config.AppSettings.Settings[keyName] != null){res = config.AppSettings.Settings[keyName].Value;}return res;}public string SetAppSettings(string keyName, string keyValue){if (config != null){if (config.AppSettings.Settings[keyName] != null)config.AppSettings.Settings[keyName].Value = keyValue;elseconfig.AppSettings.Settings.Add(keyName, keyValue);config.Save(ConfigurationSaveMode.Modified);}return GetAppSettings(keyName);}private void encryptionConn(){ConfigurationSection connectionSection = config.GetSection("connectionStrings");if (connectionSection != null){connectionSection.SectionInformation.ProtectSection("RSAProtectedConfigurationProvider");config.Save();}}}
}

View Code

WinForm读取指定的config文件的内容相关推荐

  1. Windows 核心编程研究系列之二 读取指定物理内存地址中的内容

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! [原创/ ...

  2. Android读取assets目录下文件数据内容

    Android读取assets目录下文件数据内容 Android的体系架构设计中,assets目录下的数据内容(图片.文件等等)将不会被Android系统压缩.二次处理等,assets目录下的文件 ...

  3. python读取指定路径txt文件-如何使用pandas读取txt文件中指定的列(有无标题)

    最近在倒腾一个txt文件,因为文件太大,所以给切割成了好几个小的文件,只有第一个文件有标题,从第二个开始就没有标题了. 我的需求是取出指定的列的数据,踩了些坑给研究出来了. import pandas ...

  4. Spring Boot中@ConfigurationProperties与@PropertySource的基本使用(读取指定的properties文件)

    目录 基本理论 实例 基本理论 @ConfigurationProperties 1. 与@Bean结合为属性赋值: 2. 与@PropertySource(只能用于properties文件)结合读取 ...

  5. C语言文件操作(三)读取指定路径txt文件,并输出文件内容

    #include <stdio.h> #include <stdlib.h> #include <assert.h> int main() {//读取数据int a ...

  6. python读取指定路径txt文件-python读取txt文件并取其某一列数据的示例

    菜鸟笔记 首先读取的txt文件如下: AAAAF110 0003E818 0003E1FC 0003E770 0003FFFC 90 AAAAF110 0003E824 0003E208 0003E7 ...

  7. SpringBoot学习:读取yml和properties文件的内容

    一.在SpringBoot实现属性注入: 1).添加pom依赖jar包: 1 <!-- 支持 @ConfigurationProperties 注解 --> 2 <!-- https ...

  8. matlab读取指定路径excel文件,MATLAB读取Excel文件

    调试了好几个小时,点击名字成绩就是出不来,以为是玄学,后来终于发现,哪有什么玄学,其实就是无知,丢了一句guidata(hObject, handles); 1.guidata - 存储或检索 UI ...

  9. Asp.net 自定义config文件读取

    这次项目用到了读取自定义的config文件读取,于是写了一个这样的例子,作为自己的技术积累. 我在网站根目录下新建了一个url.config 的文件 内容如下: <?xml version=&q ...

最新文章

  1. RedLock: 看完这篇文章后请不要有任何疑惑了
  2. 全图表征学习算法之无监督学习和基于卷积神经网络的监督学习
  3. wince中的hook(钩子)用法
  4. 机器学习笔记 (聚类) 层次聚类 Agglomerative Clutsering(Single-linkage、Complete-linkage,Group average)
  5. 四个角度教你评估一个产品的用户体验好坏 | PMCAFF
  6. Apache的网页和安全优化
  7. mysql数据库属性_mysql - 数据库操作和数据属性
  8. Pytorch采坑记录:每隔num_workers个iteration数据加载速度很慢
  9. linux 管理工具 scrt,Linux服务器管理之终端管理软件(SecureCRT)介绍
  10. Java程序员必读——领悟Java编程思想
  11. 模糊聚类划分matlab代码,模糊C均值聚类算法(原理+Matlab代码) - 全文
  12. GoDaddy域名解析 到 阿里云域名DNS
  13. win7浏览器主页修改不过来_Win7系统IE浏览器无法更改主页的具体解决方法
  14. 有点甜用计算机怎么谈,有点甜造句
  15. 微信 oauth2.0 php,微信公众平台OAuth2.0 认证
  16. android自定义水管流动,Android水管工游戏的简单脚本
  17. CorelDRAW X3 金箔织绣材质特效——金箔绣球(1)
  18. 【行业秘密公开】所谓的QQ刷钻业务
  19. Cadence PCB仿真 使用Allegro PCB SI为BRD文件创建通用型IBIS模型的方法图文教程
  20. 怎样将多个韵达快运单号物流中含有问题件的单号归类

热门文章

  1. 专访中科创达王璠:怎样做好嵌入式人工智能的算法开发?
  2. SegmentFault 高阳:从开发者到创业者
  3. maven学习(上)- 基本入门用法
  4. 第十二节 VMware View 6.0 菜鸟入门 部署和安装2008 R2 RDS服务
  5. mysql的错误号大全
  6. VMM2012应用指南之3-安装VMM2012
  7. Anthem库的Google Suggest 实现
  8. 【年度盘点】最受欢迎的5大Java练习项目
  9. Redis数据库操作指令
  10. SpringSecurity 权限控制之开启动态权限注解支持