WinForm读取指定的config文件的内容
config文件的使用
一、緣起
??? 最近做項目開始使用C#,因為以前一直使用的是C++,因此面向?qū)ο笏枷敕矫娴闹R還是比較全面的,反而是因沒有經(jīng)過完整、系統(tǒng)的.Net方面知識的系統(tǒng)學(xué)習(xí),經(jīng)常被一些在C#老鳥眼里幾乎是常識的小知識點給絆倒。
?
??? 為什么這么說呢,因為我在網(wǎng)絡(luò)上查找的資料的時候,經(jīng)常大部分問題,都是能夠找到或多或少的參考資料,但是這些小知識點卻很少能夠找到正確的解決方法,有也是只有提問,沒有回到,那么這種情況出現(xiàn),就只有2種解釋:
1、這個方面的問題很難,難到?jīng)]有人能夠解決;
2、這個問題太簡單,簡單到稍微熟悉的人都不屑于回答,提問者也在一番思考后,輕松找到答案。(我比較傾向這個,呵呵,因此我也把這些小知識,叫做:容易被忽略的細(xì)節(jié))
?
??? 然而,無論問題是否簡單,既然我會被絆倒,耽擱時間,肯定也會有人被同樣耽擱,因此我想把這些細(xì)節(jié)整理出來,還是具有一定意義的。
?
??? 于是,本系列文章開始...
二、問題描述
??? 除了正常情況下的config文件,使用ConfigurationManager加載,我們還可能會碰到一下這樣的情況:
1、加載非當(dāng)前應(yīng)用程序yyy.exe默認(rèn)的config文件的xxx.exe.config文件;(比如:與yyy.exe.config不在同一目錄下 或者 文件名不同)
2、加載非應(yīng)用程序的xxx.config文件;
3、讓類庫xxx.dll內(nèi)的函數(shù)讀取默認(rèn)config文件的時候,讀取的是xxx.dll同級目錄下的xxx.dll.config文件,而不是加載xxx.dll的應(yīng)用程序yyy.exe的默認(rèn)應(yīng)用程序配置文件:yyy.exe.config;
??? 以上三種情況,都不能直接使用ConfigurationManager來加載
?
三、解決過程
??? 讓我們從最基礎(chǔ)、最簡單、最常見的config文件的加載來入手,解決上面三個問題:
?
step1:研究基礎(chǔ)的config文件加載
??? config文件,是給客戶端應(yīng)用程序保存配置信息用的,一般情況,一個應(yīng)用程序只會有一個這樣的文件,在編譯之前,叫做App.config,每次使用Visual Studio編譯,都會Copy到應(yīng)用程序的生成目錄,且Rename為:應(yīng)用程序名.config。
??? 要讀取config文件內(nèi)的信息,只需要使用ConfigurationManager的相關(guān)函數(shù)和屬性即可,因此我們來研究下ConfigurationManager,看看是否能找到解決問題的相關(guān)信息。
打開MSDN,找到這樣一個方法:
OpenExeConfiguration? 已重載。 將指定的客戶端配置文件作為 Configuration 對象打開。
??? OK,要找的就是這個,因為這個方法有一個重載方法是:
OpenExeConfiguration(String)? 將指定的客戶端配置文件作為 Configuration 對象打開。
?
step2:加載非當(dāng)前應(yīng)用程序默認(rèn)的config文件
??? 于是,第一個問題的解決方案,似乎、應(yīng)該、可能找到了,按照MSDN上的說明,若我們把要打開的xxx.exe.config的路徑作為參數(shù)傳入即可,代碼如下:
???Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe.config");
???DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
???Console.WriteLine(dllInfo);
??? 但是,事情并沒有這么順利,這樣是無法打開xxx.exe.config文件的,經(jīng)過調(diào)試,發(fā)現(xiàn):config的屬性FilePath的值為:"C:\\xxx.exe.config.config",程序自己在傳入的參數(shù)后增加了“.config”作為要打開的config文件的路徑,這顯然和我們之前從MSDN上所看到的不一樣,不用說,我們被微軟小小的耍了一把。這里要傳入的參數(shù),不應(yīng)該是要打開的config的路徑,而應(yīng)該是這個config文件對應(yīng)的應(yīng)用程序的路徑,也就是說上面的代碼應(yīng)該這樣寫:
???Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe");?// 寫的是應(yīng)用程序的路徑
???DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
???Console.WriteLine(dllInfo);
??? 再次運(yùn)行,呵呵,還是不行,提示錯誤:『加載配置文件時出錯: 參數(shù)“exePath”無效。參數(shù)名: exePath』。顯然我們有被耍了,這里要傳入應(yīng)用程序路徑(exePath)沒錯,但是因為我們并沒有在xxx.exe.config文件同目錄下,加入xxx.exe文件,因此我們傳入的exePath實際上是無效的,可見為了能夠加載xxx.exe.config,我們弄一個xxx.exe文件放在一起。
??? ok,運(yùn)行,成功。
??? 小結(jié)1:第一個問題的解決方案找到:
使用ConfigurationManager.OpenExeConfiguration(string exePath)即可,同時注意2個小細(xì)節(jié):A:改方法需傳入的是exePath,而不是configPath;
B:exePath必須是有效的,因此xxx.exe和xxx.exe.config應(yīng)該成對出現(xiàn),缺一不可。
?
step3:擴(kuò)展step2的戰(zhàn)果,找到加載xxx.config的方法
??? step2已經(jīng)找到了加載xxx.exe.config的方法,觀察xxx.exe.config的名稱,發(fā)現(xiàn),若把xxx.exe看成YYY,顯然xxx.exe.config = YYY.config,也就是說:xxx.exe.config是xxx.config中比較特殊的一種,他要求config文件的文件名最后4個字母必須是“.exe”。
??? 此時,大膽推測,使用ConfigurationManager.OpenExeConfiguration(string exePath),應(yīng)該可以解決問題。
???Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx");?// 記得要有xxx文件,否則這個路徑就是無效的了。
???DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
???Console.WriteLine(dllInfo);
??? 運(yùn)行,HOHO,成功了。
??? 小結(jié)2:第二個問題和第一個問題的解決方案一樣。
?
step4:擴(kuò)展xxx.config解決問題3
??? 繼續(xù)擴(kuò)大戰(zhàn)果,還是從文件名上來找思路,我們要加載的xxx.dll.config,其實也是xxx.config中稍微特殊的一種,顯然也可以和step3那樣處理。
??? 使用OpenExeConfiguration(string exePath)來解決問題三,在dll內(nèi),碰到需要讀取config文件信息的時候,放棄使用ConfigurationManager的函數(shù)或?qū)傩灾苯荧@取,而改用OpenExeConfiguration(string exePath)加載config文件為一個Configuration對象的對應(yīng)函數(shù)或?qū)傩约纯伞?/p>
??? 小結(jié)3:第三個問題同樣可以按照第一個問題的方案來做。
?
四、額外的思考
??? 在應(yīng)用程序yyy.exe中通過ConfigurationManager可以很方便的讀取到y(tǒng)yy.exe.config文件中的信息,但在類庫中使用ConfigruationManager讀取的卻不是自動編譯生成的xxx.dll.cofig文件,而是引用類庫的應(yīng)用程序yyy.exe的yyy.exe.config文件。
?
??? 有沒有什么辦法,讓類庫中的ConfigurationManager讀取的也是他默認(rèn)的xxx.dll.config文件呢?
?
??? 其實,是可以的,不過這里涉及到了應(yīng)用程序域(AppDomain)的概念, .Net上的應(yīng)用程序都是運(yùn)行在一個應(yīng)用程序域(AppDomain)內(nèi)的,在程序啟動之初,都會默認(rèn)啟動一個AppDomain,查看MSDN可以看到AppDomain有一個屬性:SetupInformation,這個屬性保存的就是當(dāng)前域的config文件路徑;可惜,這個屬性是只讀的,所以我們默認(rèn)AppDomain的config文件路徑。
?
??? 因此,若想讓類庫能夠直接使用ConfigurationManager來讀取自己默認(rèn)的config文件,就只能把類庫放在一個新的AppDomain中執(zhí)行,并且在創(chuàng)建AppDomain的時候指定他的SetupInformation為類庫默認(rèn)的config文件路徑;AppDomain有一個用來創(chuàng)建新AppDomain的方法:CreateDomain(String, Evidence, AppDomainSetup);只要把第三個參數(shù)的屬性ConfigurationFile只想類庫默認(rèn)的config文件路徑即可。
五、附錄:實例代碼:?代碼下載
?
?
出處:https://www.cnblogs.com/bearhand/archive/2008/09/07/1279087.html
=================================================================
通過程序修改Config文件
對于config文件,一般情況下都是使用ConfigurationManager加載,然后通過讀取相應(yīng)節(jié)點的值來獲取想要的數(shù)據(jù),但是,有時候需要修改config文件的值,這時候就用到了OpenExeConfiguration()方法。
MSDN上面對該方法的解釋:ConfigurationManager.OpenExeConfiguration方法用來把指定的客戶端配置文件作為Configuration對象打開,該方法具有兩個重載:
| 名稱 | 說明 |
| ConfigurationManager.OpenExeConfiguration (ConfigurationUserLevel) | 將當(dāng)前應(yīng)用程序的配置文件作為 Configuration 對象打開。 |
| ConfigurationManager.OpenExeConfiguration (String) | 將指定的客戶端配置文件作為 Configuration 對象打開。 |
一、使用OpenExeConfiguration(ConfigurationUserLevel)重載設(shè)置當(dāng)前應(yīng)用程序的配置文件
客戶端應(yīng)用程序使用應(yīng)用于所有用戶的全局配置、應(yīng)用于單個用戶的單獨配置以及應(yīng)用于漫游用戶的配置。userLevel 參數(shù)通過指示該配置文件是不具有用戶級別(配置文件與應(yīng)用程序位于同一目錄中),還是具有一個依每個用戶而定的用戶級別(配置文件位于用戶級別所確定的應(yīng)用程序設(shè)置路徑中),從而確定所打開的配置文件的位置。
通過向 userLevel 傳遞下列值之一來指定要獲取的配置:
-
若要獲取應(yīng)用于所有用戶的 Configuration 對象,請將 userLevel 設(shè)置為 None。
-
若要獲取應(yīng)用于當(dāng)前用戶的本地 Configuration 對象,請將 userLevel 設(shè)置為 PerUserRoamingAndLocal。
-
若要獲取應(yīng)用于當(dāng)前用戶的漫游 Configuration 對象,請將 userLevel 設(shè)置為 PerUserRoaming。
注意:若要獲取資源的 Configuration 對象,您的代碼必須對它從中繼承設(shè)置的所有配置文件具有“讀取”特權(quán)。若要更新配置文件,您的代碼還必須對該配置文件及其所在目錄具有“寫入”特權(quán)。
示例程序:
1、配置文件結(jié)構(gòu)如下:
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節(jié)點的值
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); //重新加載改變的節(jié)點 ConfigurationManager.RefreshSection("appSettings");//讀取配置文件的值 string strLocalHost1Value2 = ConfigurationManager.AppSettings["LocalHost1"].ToString();//strLocalHost1Value2="http://127.0.0.1"二、使用OpenExeConfiguration(String)重載設(shè)置指定的客戶端配置文件
重載指定的客戶端config文件主要包括下面3種情況:
1、加載非當(dāng)前應(yīng)用程序yyy.exe默認(rèn)的config文件的xxx.exe.config文件(yyy.exe是當(dāng)前應(yīng)用程序,xxx.exe.config與yyy.exe.config文件不在同一目錄下)。
2、加載非應(yīng)用程序的xxx.config文件。
3、讓類庫xxx.dll內(nèi)的函數(shù)讀取默認(rèn)config文件的時候,讀取的是xxx.dll同級目錄下的xxx.dll.config文件,而不是加載xxx.dll的應(yīng)用程序yyy.exe的默認(rèn)應(yīng)用程序配置文件:yyy.exe.config。
注意:在類庫中使用ConfigruationManager讀取的不是自動編譯生成的xxx.dll.config文件,而是引用類庫的應(yīng)用程序yyy.exe的yyy.exe.config文件。
解決方法:
按照MSDN上的說明,我們把要打開的xxx.exe.config的路徑作為參數(shù)傳入,代碼如下:
1 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe.config"); 2 con.AppSettings.Settings["LocalHost2"].Value = "測試";但是程序運(yùn)行的時候報錯,經(jīng)過調(diào)試,發(fā)現(xiàn)con對象的FilePath屬性的值為:C:\Modify.exe.config.config,程序自己在傳入的參數(shù)后增加了“.config”作為要打開的config文件的路徑,因為沒有這個文件,所以程序報錯。這里要傳入的參數(shù),不應(yīng)該是要打開的config文件的路徑,而是這個config文件對應(yīng)的應(yīng)用程序的路徑,上面的代碼應(yīng)修改為:
1 //參數(shù)傳的是應(yīng)用程序的路徑 2 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe."); 3 con.AppSettings.Settings["LocalHost2"].Value = "測試";再次運(yùn)行程序,還是報錯,提示“加載配置文件時出錯:參數(shù)exePath”無效。這里要傳入應(yīng)用程序的路徑(exePath)沒錯,但是因為在xxx.exe.config文件的同一目錄下,沒有xxx.exe文件,因此我們傳入的exePath實際上是無效的,為了能夠加載xxx.exe.config文件,需要在同一目錄下增加一個xxx.exe文件。(可以在同一目錄下新建一個txt文件,修改名稱為xxx,擴(kuò)展名為.exe,這樣就可以加載xxx.exe.config配置文件了)
完整的代碼如下:
//參數(shù)傳的是應(yīng)用程序的路徑 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe"); con.AppSettings.Settings["LocalHost2"].Value = "測試"; //保存配置文件 con.AppSettings.SectionInformation.ForceSave = true; con.Save(ConfigurationSaveMode.Modified); //重新加載改變的節(jié)點 ConfigurationManager.RefreshSection("appSettings");//讀取修改后的配置文件節(jié)點值 string str = con.AppSettings.Settings["LocalHost2"].Value;//str="測試"注意:
使用ConfigurationManager.OpenExeConfiguration(string exePath)即可,同時注意2個小細(xì)節(jié):
A:改方法需傳入的是exePath,而不是configPath;
B:exePath必須是有效的,因此xxx.exe和xxx.exe.config應(yīng)該成對出現(xiàn),缺一不可。
加載非應(yīng)用程序的xxx.config文件
在上面的例子中,觀察xxx.exe.config文件的名稱,發(fā)現(xiàn),若把xxx.exe看成YYY,則xxx.exe.config=YYY.config,也就是說:xxx.exe.config是xxx.config文件的一種特殊形式,所以,可以使用如下的代碼加載xx.config文件:
//參數(shù)傳的是應(yīng)用程序的路徑 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify"); con.AppSettings.Settings["LocalHost2"].Value = "測試"; //保存配置文件 con.AppSettings.SectionInformation.ForceSave = true; con.Save(ConfigurationSaveMode.Modified); //重新加載改變的節(jié)點 ConfigurationManager.RefreshSection("appSettings");//讀取修改后的配置文件節(jié)點值 string str = con.AppSettings.Settings["LocalHost2"].Value;//str="測試"注意:C:\Modify這個文件必須要有。
加載xxx.dll.config文件:
還是從文件名上來找思路,我們要加載xxx.dll.config文件,可以和加載xxx.config文件一樣。在dll內(nèi),碰到需要讀取config文件信息的時候,放棄使用ConfigurationManager讀取節(jié)點的值,而是使用OpenExeConfiguration(string exePath)方法加載config文件為一個Configuration對象來使用。
注意:通過程序修改配置文件中節(jié)點的值,不會修改.config文件里面的值,更改只是發(fā)生在內(nèi)存中。
?
?
出處:http://www.cnblogs.com/dotnet261010/p/6597177.html
==============================================================================================
通過從網(wǎng)上的了解,和學(xué)習(xí),我們看到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>/// 默認(rèn)讀取當(dāng)前應(yīng)用程序的配置信息/// </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?
總結(jié)
以上是生活随笔為你收集整理的WinForm读取指定的config文件的内容的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [短文速读] a=a+b和a+=b的区别
- 下一篇: .NET Core 项目指定SDK版本