之前寫了篇通過Winform程序管理Windows Service 服務的文章,后來在實際使用過程中,將一些需要修改的參數順手就寫到了配置文件App.config里面。然后直接F5運行項目,想着調試下看看程序是否正常運行,這一試就試出問題了,ConfigurationManager.AppSettings.Get("message")
獲取不到參數。
ConfigurationManager
ConfigurationManager是一個提供對客戶端應用程序配置文件訪問的靜態類,此類不能被繼承。使用此類需要先將
System.Configuration.dll
引用到項目中來,具體的使用方式建議查看官方文檔。
回顧一下上文項目的目錄結構,在一個解決方案中有兩個項目分別為TaskWindowsService
(Windows服務項目)和WindowsServiceClient
(服務管理winform程序)。他們都有各自的App.config
文件。
接下來我們做一個測試:
- 各個項目的App.config中分別添加如下代碼
<appSettings>
<add key="message" value="this is TaskWindowsService"/>
</appSettings>
<appSettings>
<add key="message" value="this is WindowsServiceClient"/>
</appSettings>
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區別
引用自 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);
}
總結
問題不大,這個坑以前也踩過,但是沒有仔細的研究背后的原因,只是在兩個配置文件中都寫了一樣的參數,事情過了也就忘了。這次重新遇到就好好記錄一下,以后可不能再踩坑了。