WinForm讀取指定的config文件的內容

config文件的使用

1、緣起html


    最近作項目開始使用C#,由於之前一直使用的是C++,所以面向對象思想方面的知識仍是比較全面的,反而是因沒有通過完整、系統的.Net方面知識的系統學習,常常被一些在C#老鳥眼裏幾乎是常識的小知識點給絆倒。網絡

 

    爲何這麼說呢,由於我在網絡上查找的資料的時候,常常大部分問題,都是可以找到或多或少的參考資料,可是這些小知識點卻不多可以找到正確的解決方法,有也是隻有提問,沒有回到,那麼這種狀況出現,就只有2種解釋:
一、這個方面的問題很難,難到沒有人可以解決;
二、這個問題太簡單,簡單到稍微熟悉的人都不屑於回答,提問者也在一番思考後,輕鬆找到答案。(我比較傾向這個,呵呵,所以我也把這些小知識,叫作:容易被忽略的細節)
app

 

    然而,不管問題是否簡單,既然我會被絆倒,耽擱時間,確定也會有人被一樣耽擱,所以我想把這些細節整理出來,仍是具備必定意義的。ide

 

    因而,本系列文章開始...函數


2、問題描述post


    除了正常狀況下的config文件,使用ConfigurationManager加載,咱們還可能會碰到一下這樣的狀況:
一、加載非當前應用程序yyy.exe默認的config文件的xxx.exe.config文件;(好比:與yyy.exe.config不在同一目錄下 或者 文件名不一樣)
二、加載非應用程序的xxx.config文件;
三、讓類庫xxx.dll內的函數讀取默認config文件的時候,讀取的是xxx.dll同級目錄下的xxx.dll.config文件,而不是加載xxx.dll的應用程序yyy.exe的默認應用程序配置文件:yyy.exe.config;
    以上三種狀況,都不能直接使用ConfigurationManager來加載學習

 

3、解決過程測試


    讓咱們從最基礎、最簡單、最多見的config文件的加載來入手,解決上面三個問題:this

 

step1:研究基礎的config文件加載加密

    config文件,是給客戶端應用程序保存配置信息用的,通常狀況,一個應用程序只會有一個這樣的文件,在編譯以前,叫作App.config,每次使用Visual Studio編譯,都會Copy到應用程序的生成目錄,且Rename爲:應用程序名.config。
    要讀取config文件內的信息,只須要使用ConfigurationManager的相關函數和屬性便可,所以咱們來研究下ConfigurationManager,看看是否能找到解決問題的相關信息。
打開MSDN,找到這樣一個方法:

OpenExeConfiguration  已重載。 將指定的客戶端配置文件做爲 Configuration 對象打開。

    OK,要找的就是這個,由於這個方法有一個重載方法是:

OpenExeConfiguration(String)  將指定的客戶端配置文件做爲 Configuration 對象打開。

 

step2:加載非當前應用程序默認的config文件

    因而,第一個問題的解決方案,彷佛、應該、可能找到了,按照MSDN上的說明,若咱們把要打開的xxx.exe.config的路徑做爲參數傳入便可,代碼以下:

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe.config");
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    可是,事情並無這麼順利,這樣是沒法打開xxx.exe.config文件的,通過調試,發現:config的屬性FilePath的值爲:"C:\\xxx.exe.config.config",程序本身在傳入的參數後增長了「.config」做爲要打開的config文件的路徑,這顯然和咱們以前從MSDN上所看到的不同,不用說,咱們被微軟小小的耍了一把。這裏要傳入的參數,不該該是要打開的config的路徑,而應該是這個config文件對應的應用程序的路徑,也就是說上面的代碼應該這樣寫:

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe"); // 寫的是應用程序的路徑
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    再次運行,呵呵,仍是不行,提示錯誤:『加載配置文件時出錯: 參數「exePath」無效。參數名: exePath』。顯然咱們有被耍了,這裏要傳入應用程序路徑(exePath)沒錯,可是由於咱們並無在xxx.exe.config文件同目錄下,加入xxx.exe文件,所以咱們傳入的exePath其實是無效的,可見爲了可以加載xxx.exe.config,咱們弄一個xxx.exe文件放在一塊兒。

    ok,運行,成功。

    小結1:第一個問題的解決方案找到:

使用ConfigurationManager.OpenExeConfiguration(string exePath)便可, 同時注意2個小細節
A:改方法需傳入的是exePath,而不是configPath;
B:exePath必須是有效的,所以xxx.exe和xxx.exe.config應該成對出現,缺一不可。

 

step3:擴展step2的戰果,找到加載xxx.config的方法

    step2已經找到了加載xxx.exe.config的方法,觀察xxx.exe.config的名稱,發現,若把xxx.exe當作YYY,顯然xxx.exe.config = YYY.config,也就是說:xxx.exe.config是xxx.config中比較特殊的一種,他要求config文件的文件名最後4個字母必須是「.exe」。

    此時,大膽推測,使用ConfigurationManager.OpenExeConfiguration(string exePath),應該能夠解決問題。

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx"); // 記得要有xxx文件,不然這個路徑就是無效的了。
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    運行,HOHO,成功了。

    小結2:第二個問題和第一個問題的解決方案同樣。

 

step4:擴展xxx.config解決問題3

    繼續擴大戰果,仍是從文件名上來找思路,咱們要加載的xxx.dll.config,其實也是xxx.config中稍微特殊的一種,顯然也能夠和step3那樣處理。

    使用OpenExeConfiguration(string exePath)來解決問題三,在dll內,碰到須要讀取config文件信息的時候,放棄使用ConfigurationManager的函數或屬性直接獲取,而改用OpenExeConfiguration(string exePath)加載config文件爲一個Configuration對象的對應函數或屬性便可。

    小結3:第三個問題一樣能夠按照第一個問題的方案來作。

 

4、額外的思考

    在應用程序yyy.exe中經過ConfigurationManager能夠很方便的讀取到yyy.exe.config文件中的信息,但在類庫中使用ConfigruationManager讀取的卻不是自動編譯生成的xxx.dll.cofig文件,而是引用類庫的應用程序yyy.exe的yyy.exe.config文件。

 

    有沒有什麼辦法,讓類庫中的ConfigurationManager讀取的也是他默認的xxx.dll.config文件呢?

 

    其實,是能夠的,不過這裏涉及到了應用程序域(AppDomain)的概念, .Net上的應用程序都是運行在一個應用程序域(AppDomain)內的,在程序啓動之初,都會默認啓動一個AppDomain,查看MSDN能夠看到AppDomain有一個屬性:SetupInformation,這個屬性保存的就是當前域的config文件路徑;惋惜,這個屬性是隻讀的,因此咱們默認AppDomain的config文件路徑。

 

    所以,若想讓類庫可以直接使用ConfigurationManager來讀取本身默認的config文件,就只能把類庫放在一個新的AppDomain中執行,而且在建立AppDomain的時候指定他的SetupInformation爲類庫默認的config文件路徑;AppDomain有一個用來建立新AppDomain的方法:CreateDomain(String, Evidence, AppDomainSetup);只要把第三個參數的屬性ConfigurationFile只想類庫默認的config文件路徑便可。


5、附錄:實例代碼: 代碼下載

 

 

出處:https://www.cnblogs.com/bearhand/archive/2008/09/07/1279087.html

=================================================================

經過程序修改Config文件

對於config文件,通常狀況下都是使用ConfigurationManager加載,而後經過讀取相應節點的值來獲取想要的數據,可是,有時候須要修改config文件的值,這時候就用到了OpenExeConfiguration()方法。

MSDN上面對該方法的解釋:ConfigurationManager.OpenExeConfiguration方法用來把指定的客戶端配置文件做爲Configuration對象打開,該方法具備兩個重載:

名稱 說明
ConfigurationManager.OpenExeConfiguration (ConfigurationUserLevel) 將當前應用程序的配置文件做爲 Configuration 對象打開。
ConfigurationManager.OpenExeConfiguration (String) 將指定的客戶端配置文件做爲 Configuration 對象打開。

1、使用OpenExeConfiguration(ConfigurationUserLevel)重載設置當前應用程序的配置文件

客戶端應用程序使用應用於全部用戶的全局配置、應用於單個用戶的單獨配置以及應用於漫遊用戶的配置。userLevel 參數經過指示該配置文件是不具備用戶級別(配置文件與應用程序位於同一目錄中),仍是具備一個依每一個用戶而定的用戶級別(配置文件位於用戶級別所肯定的應用程序設置路徑中),從而肯定所打開的配置文件的位置。

經過向 userLevel 傳遞下列值之一來指定要獲取的配置:

  • 若要獲取應用於全部用戶的 Configuration 對象,請將 userLevel 設置爲 None。

  • 若要獲取應用於當前用戶的本地 Configuration 對象,請將 userLevel 設置爲 PerUserRoamingAndLocal。

  • 若要獲取應用於當前用戶的漫遊 Configuration 對象,請將 userLevel 設置爲 PerUserRoaming。

注意:若要獲取資源的 Configuration 對象,您的代碼必須對它從中繼承設置的全部配置文件具備「讀取」特權。若要更新配置文件,您的代碼還必須對該配置文件及其所在目錄具備「寫入」特權。

示例程序:

一、配置文件結構以下:

複製代碼
 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>
複製代碼

二、經過程序修改LocalHost1節點的值

複製代碼
 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);
//從新加載改變的節點
ConfigurationManager.RefreshSection("appSettings");

//讀取配置文件的值
string strLocalHost1Value2 = ConfigurationManager.AppSettings["LocalHost1"].ToString();//strLocalHost1Value2="http://127.0.0.1"
複製代碼

2、使用OpenExeConfiguration(String)重載設置指定的客戶端配置文件

重載指定的客戶端config文件主要包括下面3種狀況:

一、加載非當前應用程序yyy.exe默認的config文件的xxx.exe.config文件(yyy.exe是當前應用程序,xxx.exe.config與yyy.exe.config文件不在同一目錄下)。

二、加載非應用程序的xxx.config文件。

三、讓類庫xxx.dll內的函數讀取默認config文件的時候,讀取的是xxx.dll同級目錄下的xxx.dll.config文件,而不是加載xxx.dll的應用程序yyy.exe的默認應用程序配置文件:yyy.exe.config。

注意:在類庫中使用ConfigruationManager讀取的不是自動編譯生成的xxx.dll.config文件,而是引用類庫的應用程序yyy.exe的yyy.exe.config文件。

解決方法:

按照MSDN上的說明,咱們把要打開的xxx.exe.config的路徑做爲參數傳入,代碼以下:

1 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe.config");
2 con.AppSettings.Settings["LocalHost2"].Value = "測試";

可是程序運行的時候報錯,通過調試,發現con對象的FilePath屬性的值爲:C:\Modify.exe.config.config,程序本身在傳入的參數後增長了「.config」做爲要打開的config文件的路徑,由於沒有這個文件,因此程序報錯。這裏要傳入的參數,不該該是要打開的config文件的路徑,而是這個config文件對應的應用程序的路徑,上面的代碼應修改成:

1 //參數傳的是應用程序的路徑
2 Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe.");
3 con.AppSettings.Settings["LocalHost2"].Value = "測試";

再次運行程序,仍是報錯,提示「加載配置文件時出錯:參數exePath」無效。這裏要傳入應用程序的路徑(exePath)沒錯,可是由於在xxx.exe.config文件的同一目錄下,沒有xxx.exe文件,所以咱們傳入的exePath其實是無效的,爲了可以加載xxx.exe.config文件,須要在同一目錄下增長一個xxx.exe文件。(能夠在同一目錄下新建一個txt文件,修更名稱爲xxx,擴展名爲.exe,這樣就能夠加載xxx.exe.config配置文件了)

完整的代碼以下:

複製代碼
//參數傳的是應用程序的路徑
Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify.exe");
con.AppSettings.Settings["LocalHost2"].Value = "測試";
//保存配置文件
con.AppSettings.SectionInformation.ForceSave = true;
con.Save(ConfigurationSaveMode.Modified);
//從新加載改變的節點
ConfigurationManager.RefreshSection("appSettings");

//讀取修改後的配置文件節點值
string str = con.AppSettings.Settings["LocalHost2"].Value;//str="測試"
複製代碼

注意:

使用ConfigurationManager.OpenExeConfiguration(string exePath)便可,同時注意2個小細節:
A:改方法需傳入的是exePath,而不是configPath;
B:exePath必須是有效的,所以xxx.exe和xxx.exe.config應該成對出現,缺一不可。

加載非應用程序的xxx.config文件

在上面的例子中,觀察xxx.exe.config文件的名稱,發現,若把xxx.exe當作YYY,則xxx.exe.config=YYY.config,也就是說:xxx.exe.config是xxx.config文件的一種特殊形式,因此,可使用以下的代碼加載xx.config文件:

複製代碼
//參數傳的是應用程序的路徑
Configuration con = ConfigurationManager.OpenExeConfiguration("C:\\Modify");
con.AppSettings.Settings["LocalHost2"].Value = "測試";
//保存配置文件
con.AppSettings.SectionInformation.ForceSave = true;
con.Save(ConfigurationSaveMode.Modified);
//從新加載改變的節點
ConfigurationManager.RefreshSection("appSettings");

//讀取修改後的配置文件節點值
string str = con.AppSettings.Settings["LocalHost2"].Value;//str="測試"
複製代碼

注意:C:\Modify這個文件必需要有。

加載xxx.dll.config文件:

仍是從文件名上來找思路,咱們要加載xxx.dll.config文件,能夠和加載xxx.config文件同樣。在dll內,碰到須要讀取config文件信息的時候,放棄使用ConfigurationManager讀取節點的值,而是使用OpenExeConfiguration(string exePath)方法加載config文件爲一個Configuration對象來使用。

注意:經過程序修改配置文件中節點的值,不會修改.config文件裏面的值,更改只是發生在內存中。

 

 

出處:http://www.cnblogs.com/dotnet261010/p/6597177.html

==============================================================================================

經過從網上的瞭解,和學習,咱們看到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>
        /// 默認讀取當前應用程序的配置信息
        /// </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;
                else
                    config.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;
                else
                    config.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
相關文章
相關標籤/搜索