C# ConfigurationManager 多个配置文件读取问题
之前写了篇的文章,后来在实际使用过程中,将一些需要修改的参数顺手就写到了配置文件App.config里面。然后直接F5运行项目,想着调试下看看程序是否正常运行,这一试就试出问题了,ConfigurationManager.AppSettings.Get("message")
获取不到参数。
ConfigurationManager
ConfigurationManager是一个提供对客户端应用程序配置文件访问的静态类,此类不能被继承。使用此类需要先将
System.Configuration.dll
引用到项目中来,具体的使用方式建议查看官方文档。
回顾一下上文项目的目录结构,在一个解决方案中有两个项目分别为TaskWindowsService
(Windows服务项目)和WindowsServiceClient
(服务管理winform程序)。他们都有各自的App.config
文件。
接下来我们做一个测试:
- 各个项目的App.config中分别添加如下代码
ps:(两个配置文件都有了,总不至于读不到数据了吧~)
- 在TaskWindowsService中引用
System.Configuration.dll
,并使用ConfigurationManager
读取配置文件,记录到日志中
public static void ConfigTest()
{
LogHelper.Log(ConfigurationManager.AppSettings.Get("message"));
}
- 运行
WindowsServiceClient
并调用ConfigTest()
方法
public Form1()
{
InitializeComponent();
SkpDomain.ConfigTest();
}
- 注册并启动
TaskWindowsService
在服务启动时调用ConfigTest()
方法
protected override void OnStart(string[] args)
{
SkpDomain.ConfigTest();
}
看一下输出的日志,好玩的东西来了。居然两个app.config
文件都光顾到了。从顺序来看,先打开读取的是WindowsServiceClient
的配置文件,再是TaskWindowsService
启动时读取的配置文件。
{"Time":"2020-10-28 17:38:55","Message":"this is WindowsServiceClient","Data":null}
{"Time":"2020-10-28 17:38:57","Message":"this is TaskWindowsService","Data":null}
从这里可以得出一个结论:ConfigurationManager读取的配置文件是由当前运行的项目决定的
这里引用一段
app.config, *.exe.config 和 *.vshost.exe.config区别
引用自
1. app.config
作为开发时配置参数的文件,可以在vs开发时右键属性设置是否复制到可执行程序同目录下(默认始终不复制)。
在不复制的情况下,编译生成可执行程序时会copy该文件为.exe.config文件和.vshost.exe.config文件。
这样的话,在/bin/debug/ 或者/bin/release/目录下就不会有app.config文件了,对应的有exe.config和vshost.exe.config。
以后运行exe文件所操作的配置文件(通过System.Configuration
对象,System.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
)直接修改的是exe.config文件。
2.*.exe.config
vs调试编译时,如果app.config文件有修改,则会重新copy覆盖到exe.config和vshost.exe.config文件中,
否则exe.config不会改变。exe.config文件为程序实际运行时(直接运行.exe程序)直接操作的配置文件。
3.*.vshost.exe.config
该文件主要是在vs调试运行时起作用,在调试运行程序时(*vshost.exe -> *.exe)先copy *.exe.config覆盖
*.vshost.exe.config,然后运行程序时操作的配置文件为 .vshost.exe.config。在调试程序结束时(.exe -> *.vshost.exe)再次copy .exe.config覆盖.vshost.exe.config。 所以调试情况下无论怎么修改配置文件,程序退出后都不会修改配置文件(还原了)。
如果一定要强行指定获取某一个程序的配置文件,可以这么做:
public static void ConfigTest()
{
var servicePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TaskWindowsService.exe");//一定是运行程序路径,而不是配置文件路径
LogHelper.Log(ConfigurationManager.OpenExeConfiguration(servicePath).AppSettings.Settings["message"].Value);
}
总结
问题不大,这个坑以前也踩过,但是没有仔细的研究背后的原因,只是在两个配置文件中都写了一样的参数,事情过了也就忘了。这次重新遇到就好好记录一下,以后可不能再踩坑了。