C# ConfigurationManager 多个配置文件读取问题

之前写了篇通过Winform程序管理Windows Service 服务的文章,后来在实际使用过程中,将一些需要修改的参数顺手就写到了配置文件App.config里面。然后直接F5运行项目,想着调试下看看程序是否正常运行,这一试就试出问题了,ConfigurationManager.AppSettings.Get("message")获取不到参数。

ConfigurationManager

ConfigurationManager是一个提供对客户端应用程序配置文件访问的静态类,此类不能被继承。使用此类需要先将System.Configuration.dll引用到项目中来,具体的使用方式建议查看官方文档

回顾一下上文项目的目录结构,在一个解决方案中有两个项目分别为TaskWindowsService(Windows服务项目)和WindowsServiceClient(服务管理winform程序)。他们都有各自的App.config文件。

接下来我们做一个测试:

  1. 各个项目的App.config中分别添加如下代码
<appSettings>
	<add key="message" value="this is TaskWindowsService"/>
</appSettings>

<appSettings>
	<add key="message" value="this is WindowsServiceClient"/>
</appSettings>

ps:(两个配置文件都有了,总不至于读不到数据了吧~)

  1. 在TaskWindowsService中引用System.Configuration.dll,并使用ConfigurationManager读取配置文件,记录到日志中
public static void ConfigTest()
{
    LogHelper.Log(ConfigurationManager.AppSettings.Get("message"));
}
  1. 运行WindowsServiceClient并调用ConfigTest()方法
public Form1()
{
    InitializeComponent();
    SkpDomain.ConfigTest();
}
  1. 注册并启动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区别

引用自 https://www.cnblogs.com/leenice/p/5286451.html

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);
}

总结

问题不大,这个坑以前也踩过,但是没有仔细的研究背后的原因,只是在两个配置文件中都写了一样的参数,事情过了也就忘了。这次重新遇到就好好记录一下,以后可不能再踩坑了。

posted @ 2020-10-28 19:11  傅小灰  阅读(2125)  评论(0编辑  收藏  举报