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

    总结

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

  • 相关阅读:
    拯救祭天的程序员——事件溯源模式
    啥?SynchronousQueue和钟点房一个道理
    程序员应该掌握的一些 Linux 命令
    Linux 环境下使用 sqlplus 访问远程 Oracle 数据库
    我对鸿蒙OS的一些看法
    我对技术潮流的一些看法
    git merge --ff/--no-ff/--ff-only 三种选项参数的区别
    go语言的初体验
    完全使用 VSCode 开发的心得和体会
    重复代码的克星,高效工具 VSCode snippets 的使用指南
  • 原文地址:https://www.cnblogs.com/cplemom/p/13892829.html
Copyright © 2020-2023  润新知