組態設定
認識組態檔
系統開發時,一定會使用組態檔,來記錄一些可能會變動的資訊,以避免因 hard-code 所造成的不方便。 .NET底下的 System.Configuration 命名空間所提供的類別,就是用來管理組態設定用的,讓開發者可以更輕鬆的存取這些資訊。
底下是開發系統常會使用到的組態檔
- 應用程式組態檔( XXXX.exe.config ):這個檔一般與執行檔放在同一層目錄。
- 電腦組態檔( Machine.config ):包含套用於整個電腦的設定值。這個檔案位於 %system32%\Microsoft.NET\Framework\[版本號]\Config 目錄。
- Web 組態檔( Web.config ):這個檔是使用在網站專案的組態檔。
組態檔是一個 XML 文件,其中包含了許多的項目,詳情結構可參考.NET Framework 的組態檔結構描述。 雖然這個 XML 文件也可以透過 XmlSerializer 以取得資訊內容,不過, 針對組態檔,直接使用 System.Configuration 命名空間所提供的 Configuration 、 ConfigurationManager 類別,就可以快速方便讀取組態檔中的設定值。
Configuration 的屬性和方法
Configuration 這個類別是用來記載描述電腦中特定的組態檔類別
屬性
- AppSettings :取得 <appSettings> 區段的組態資料。
- ConnectionStrings :取得 <connectionStrings> 區段的組態資料。
- FilePath :取得組態檔的實體路徑。
- Sections :取得這個 Configuration 物件所定義的區段集合。
- SectionGroups :取得這個組態所定義的區段群組集合。
- RootSectionGroup :取得這個 Configuration 物件的根 ConfigurationSectionGroup。
方法
- GetSection :傳回指定的 ConfigurationSection 物件。
- GetSectionGroup :取得指定的 ConfigurationSectionGroup 物件。
- Save :將包含在這個 Configuration 物件中的組態設定寫入至目前的 XML 組態檔。
- SaveAs :將包含在這個 Configuration 物件中的組態設定寫入至指定的 XML 組態檔。
ConfigurationManager 的屬性和方法
這個類別是用來管理操作組態檔的類別
屬性
- AppSettings :對應到組態檔的 <appSettings> 區段。
- ConnectionStrings :對應到組態檔的 <connectionStrings> 區段。
方法
- GetSection :取得組態區段
- OpenExeConfiguration :開啟應用程式組態檔
- OpenMachineConfiguration :開啟電腦組態檔
- OpenMappedExeConfiguration :開啟指定的應用程式組態檔
- OpenMappedMachineConfiguration :開啟指定的電腦組態檔
- RefreshSection :重新整理具名區段,以便下次擷取它時,會從磁碟重新讀取它。
如何開啟組態檔
加入 System.Configuration 參考
因為 Visual Studio 的預設參考不包含 System.Configuration 組件,所以使用這個類別之前,必須先手動加入參考,才可以引用的到 System.Configuration 命名空間。
//開啟應用程式組態檔 //同 XXXX.exe 目錄 Configuration config1 = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //開啟特定的應用程式組態檔 string ExeFileName = @"C:\App1.config"; Debug.Assert(File.Exists(ExeFileName),"file is miss"); //判斷檔案是否存在 ExeConfigurationFileMap MyMap = new ExeConfigurationFileMap(); MyMap.ExeConfigFilename = ExeFileName; Configuration config2 = ConfigurationManager.OpenMappedExeConfiguration(MyMap, ConfigurationUserLevel.None); //開啟電腦組態檔 //%system32%\Microsoft.NET\Framework\[版本號]\Config 目錄。 Configuration config3 = ConfigurationManager.OpenMachineConfiguration(); //開啟特定的電腦組態檔 Configuration config4 = ConfigurationManager.OpenMappedMachineConfiguration(MyMap);
通用設定
什麼是通用設定
前面提過,整個組態檔包含了許多項目,而「通用設定」指的是其中幾項與決定應用程式如何執行有關的組態設定項目。例如:
1.<supportedRuntime>:若開發專案的.NET版本與執行環境的版本不同,可以在這個區段指定RunTime的版本。
2.<developmentMode>:在開發階段將某組件設定成共用組件。
3.<codeBase>:指定某個組件的位置與版本。
4.<appSettings>:與應用程式設定相關的區塊
5.<connectionStrings>:與資料庫連線設定相關的區塊
下面這些例子,示範了上面幾項設定內容:
指定Runtime版本
依 <supportedRun> 中指定的版本啟用 Framework 版本。
<startup> <supportedRuntime version="v2.0.50727"/> </startup>
指定使用組件位置:
1.加入一個名為 DEVPATH 的環境變數,並指定組件位置。
2.將 developmentMode 的值設為 true。
<runtime> <developmentMode developerInstallation="true"/> </runtime>
使用 <codeBase> 同時指定組件的位置與版本
<configuration> <runtime> <assemblyBinding xmlns="schemaname"> <dependentAssembly> <assemblyIdentity name="myprogram" publicKeyToken="xxxxxxxxx" culture="en-us"/> <assemblyIdentity name="assembly name" publicKeyToken="xxxxxxxxx" culture="en-us"/> <codeBase version="x.0.0.0" href="http://www.adatum.com/myprogram.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
使用 <appSettings>
<appSettings> <add key="ConnString" value="Data Source=localhost; Initial Catalog=DBNAME; User ID=sa; Password=Password"/> <add key="DBAssemblyName" value="DBProvider"/> <add key="DBClassName" value="SqlDBObject"/> </appSettings>
使用 <connectionStrings>
<connectionStrings> <clear/> <add name="AdventureWorksString" providerName="System.Data.SqlClient" connectionString="Data Source=localhost; Initial Catalog=DBNAME; User ID=sa; Password=Password; Integrated Security=true"/> </connectionStrings>
上面資訊中,比較特別的是<appSettings>與<connectionStrings>這二個區段:
- 透過 ConfigurationManager.AppSettings 屬性,可取得 NameValueCollection 型態的集合物件,它的項目是以 key/value 的方式存放。
- 透過 ConfigurationManager.ConnectionStrings 屬性,可取得 ConnectionStringSettingsCollection 型態的集合物件,它的項目是以 name/connectionString 的方式存放。
底下示範如何操作組態檔
如何讀取組態檔中 appSettings 區段的項目
透過 ConfigurationManager.AppSettings 方法就可以取得 AppSettings 區段下的所有設定項目,其回傳值是一個 NameValueCollection 型別的集合。
//0) 已過時用法 string ConnString = ConfigurationSettings.AppSettings["ConnString"]; //1) 取得單一個項目 string ConnString = ConfigurationManager.AppSettings["ConnString"]; //2) 取得整個<appSettings>區段 NameValueCollection AllAppSett ings = ConfigurationManager.AppSettings; ConnString = AllAppSettings["ConnString"]; //3) 列舉<appSettings> 區段 foreach (string key in AllAppSettings) Console.WriteLine("Key/Value:{0} = {1}", key, AllAppSettings[key]); //由 key 取 value
如何修改組態檔中 appSettings 區段的項目
要修改組態設定值,必須先開啟組態檔,再透過 Configuration.AppSettings 這個屬性回傳 AppSettingsSection 型別的組態區段資料,再使用其 Settings 方法,就可新增修改刪除區段中的項目。步驟如下:
- 開啟組態檔。
- 透過 Configuration.AppSettings.Settings 取得 appSettings 區段的集合物件。
- 新增或修改集合中的資料。
- 透過 Configuration.Save 方法回存資料到 appSettings 區段。
//開啟組態檔 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //取得 AppSettings 區段的組態設定值 KeyValueConfigurationCollection appSettings = config.AppSettings.Settings; //新增或變更 AppSettings 區段的項目 appSettings["key1"].Value = "value 111"; //修改 appSettings.Add("key2", "value2"); //新增 //儲存到 AppSettings 區段 (要注意使用者的存取權限) config.Save();
PS.
當在 Visual Studio 中執行 debug 模式,此時使用的組態檔是 /bin/Debug/XXXX.vshost.exe.config,
而且,即使執行了 Save() 動作,設定值也是不會變更的。
如何讀取組態檔中 connectionStrings 區段的項目
透過 ConfigurationManager.ConnectionStrings 可以取得 connectionStrings 區段下的所有設定項目,其回傳值是一個 ConnectionStringSettingsCollection 型別的集合,集合內的元素則是由 ConnectionStringSettings 物件組成。 透過 ConnectionStringSettings 物件就可以取出設定項目中 name 、 connectionString 、 providerName 三個屬性值。
//1) 取得單一個項目 ConnectionStringSettings myConn = ConfigurationManager.ConnectionStrings["AdventureWorksString"]; //2) 取得整個<connectionStrings> 區段 ConnectionStringSettingsCollection MyConnections = ConfigurationManager.ConnectionStrings; // 由集合中取出一個項目 ConnectionStringSettings myConnSetting = MyConnections["AdventureWorksString"]; String ConnString = myConnSetting.ConnectionString; //3) 列舉<connectionStrings> 區段 if (MyConnections != null) { StringBuilder sb = new StringBuilder(); foreach (ConnectionStringSettings ConnSetting in MyConnections) { sb.AppendLine("ConnectionString = " + ConnSetting.ConnectionString); sb.AppendLine("Name = " + ConnSetting.Name); sb.AppendLine("ProviderName = " + ConnSetting.ProviderName); } Console.WriteLine(sb.ToString()); }
如何修改組態檔中 connectionStrings 區段的項目
- 開啟組態檔。
- 透過 Configuration.ConnectionStrings.ConnectionStrings 取得 connectionStrings 區段的集合物件。
- 新增或修改集合中的資料。
- 透過 Configuration.Save 方法回存資料到 connectionStrings 區段。
//開啟組態檔 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //取得 connectionStrings 區段的組態設定值 ConnectionStringSettingsCollection Connections = config.ConnectionStrings.ConnectionStrings; //新增或變更項目 Connections["Conn1"].ConnectionString = "Data Source=localhost; Initial Catalog=DBNAME1;..."; //修改 Connections.Add(new ConnectionStringSettings("Conn2", "Data Source=localhost; Initial Catalog=DBNAME;")); //新增 //儲存 config.Save();
如何讀取 Web 應用程式的組態檔
如果是 Web 應用程式的話,可改用 WebConfigurationManager 來管理組態資訊,用法幾乎是一樣的:
Console.SetOut(Response.Output); //1)直接取得<appSettings>底下,Key="ConnString"這個項目的設定值 string ConnString = WebConfigurationManager.AppSettings["ConnString"]; //2)取得整個<appSettings>區段 NameValueCollection AllAppSettings = WebConfigurationManager.AppSettings; //3)列舉<appSettings>區段 IEnumerator SettingsEnumerator = AllAppSettings.Keys.GetEnumerator(); while (SettingsEnumerator.MoveNext()) { Response.Write(string.Format("Item: {0} Value: {1} <BR>", SettingsEnumerator.Current, AllAppSettings[(string)SettingsEnumerator.Current])); } //1)直接取得<connectionStrings>底下,Name="AdventureWorksString"這個項目的設定值 ConnectionStringSettings myConn = WebConfigurationManager.ConnectionStrings["AdventureWorksString"]; //2)取得<connectionStrings>區段 ConnectionStringSettingsCollection MyConnections = WebConfigurationManager.ConnectionStrings; //3)列舉<connectionStrings>區段 if (MyConnections != null) { StringBuilder sb = new StringBuilder(); foreach (ConnectionStringSettings ConnSetting in MyConnections) { sb.AppendLine("Full Connection String: " + ConnSetting.ConnectionString + "<BR>"); sb.AppendLine("Section Name: " + ConnSetting.Name + "<BR>"); sb.AppendLine("Provider Name: " + ConnSetting.ProviderName + "<BR>"); } Response.Write(sb.ToString()); }
應用程式設定
什麼是應用程式設定
「應用程式設定」指的是套用到整個應用程式的組態設定項目,例如,專案名稱,公司名稱,Web Service的URL等等的變數。
使用應用程式設定,除了快速方便之外,另一個好處是,這些設定值是支援強型別的。
ApplicationSettingsBase :這個類別是這個機制的主要核心物件。 透過設定檔設計工具可以方便管理這些設定值,因為系統會自動建立這些設定值的類別,這個類別會就是繼承自 ApplicationSettingsBase 。 若我們要自已手寫一個類別以讀取應用程式設定檔,也只須繼承這個類別即可。
應用程式設定值有一個屬性,稱為使用範圍,可以有2種設定:一是 Application ,另一個是 User
- Application:
指的是整個應用程式的所有使用者共用的資訊,例如存放專案名稱、公司名稱等。這個區段的設定值是唯讀的。 這個範圍的設定值會存放在 <applicationSettings> 區段內。 - User:
指的是整個各別使用者使用的資訊,例如存放使用者姓名、喜好設定等。這個區段的設定值可供讀寫。 這個範圍的設定值會存放在 <userSettings> 區段內。
如何設定預設的應用程式設定檔
在專案的 Properties 目錄底下,預設會有一個設定檔 (Settings.settings),只要點擊這個檔案,或者在專案的 Property 項目上,按右鍵,選擇開啟,就可以開啟編輯工具,進行維護。操作步驟如下:
開啟設定檔
設定屬性名稱、型別、範圍
如何讀取預設的應用程式設定檔
假設我們在預設的應用程式設定檔中,加入下列項目:
系統會自動幫我們產生 Settings 這個類別,透過以下的方法,就可以直接以物件導向的方法取得各個設定值。
//讀取應用程式設定檔 Settings 這個設定檔,是系統預設的設定檔類別 Console.WriteLine(Settings.Default.Setting1); Console.WriteLine(Settings.Default.Setting2); Console.WriteLine(Settings.Default.Setting3); Console.WriteLine(Settings.Default.Setting4); //abc123 //abc456 //公司名稱 //系統名稱
如何新增自建的應用程式設定檔
應用程式設定檔可以多個,也不一定要放在專案的 Property 項目底下。你可以自行新增自訂的應用程式設定檔,如下圖所示:
新增設定檔
設定檔不一定要在 Properties 目錄底下
如何讀取自建的應用程式設定檔
同樣的,當新增一個應用程式設定檔時,系統也會自動幫我們建立這個設定檔類別,透過以下的方法,就可以直接存取設定檔中的設定值。假設設定內容如下:
有二種方式存取。你可以新增一個設定檔類別的實體去存取設定值,或者是使用 Default 這個 static instance 取得屬性值。
//讀取應用程式設定檔,SampleApp 這個設定檔,是透過設計工具幫我們建立的類別 SampleApp sa = new SampleApp(); Console.WriteLine(sa.myName); Console.WriteLine(sa.myBirthday.ToString()); Console.WriteLine(sa.myEmail); Color c = sa.sysColor; Console.WriteLine(sa.sysProjectName); //若不想建立類別實體,也可以使用Default這個static instance取得屬性值 Console.WriteLine(SampleApp.Default.myName); Console.WriteLine(SampleApp.Default.myBirthday.ToString()); Console.WriteLine(SampleApp.Default.myEmail); Color c2 = SampleApp.Default.sysColor; Console.WriteLine(SampleApp.Default.sysProjectName);
如何自行撰寫自訂應用程式設定檔類別
前面提過, ApplicationSettingsBase 是應用程式設定檔的基底類別,若要自行撰寫設定檔類別,首先就要繼承這個類別。
下列示範如何自行撰寫繼承自 ApplicationSettingsBase 類別,以讀取應用程式設定檔
//讀取應用程式設定檔 SampleApp2這個設定檔,是自行撰寫繼承自ApplicationSettingsBase的類別 SampleApp2 sa2 = new SampleApp2(); Console.WriteLine(sa2.myName); Console.WriteLine(sa2.myBirthday.ToString()); Console.WriteLine(sa.myEmail); Color c3 = sa2.sysColor; Console.WriteLine(sa2.sysProjectName); class SampleApp2 : ApplicationSettingsBase { [UserScopedSetting()] //將這個設定值的使用範圍設定為:User [DefaultSettingValueAttribute("vito")] //設定預設值 public string myName { get { return (String)this["myName"]; } set { this["myName"] = value; } } [UserScopedSetting()] [DefaultSettingValueAttribute("1911/01/01")] public System.DateTime myBirthday { get { return (DateTime)this["myBirthday"]; } set { this["myBirthday"] = value; } } [UserScopedSetting()] [DefaultSettingValueAttribute("")] public string myEmail { get { return (string)this["myEmail"]; } set { this["myEmail"] = value; } } [ApplicationScopedSetting()] //將這個設定值的使用範圍設定為:Application [DefaultSettingValueAttribute("255, 255, 255")] public Color sysColor { get { return (Color)this["sysColor"]; } set { this["sysColor"] = value; } } [ApplicationScopedSetting()] [DefaultSettingValueAttribute("aaa bbb")] public string sysProjectName { get { return (string)this["sysProjectName"]; } set { this["sysProjectName"] = value; } } }
如何以程式碼修改設定值
不管增加了幾個應用程式設定檔,所有應用程式設定檔的資訊內容,都會被複製存一份放在 app.config 底下。 如果將設定值的使用範圍設為 User ,就會放在 <userSettings> 區段內;如果將設定值的使用範圍設為 Application ,就會放在 <applicationSettings> 區段內。
下列程式碼示範如何讀取與變更設定值:
private void button8_Click(object sender, EventArgs e) { //讀取設定值 SampleApp setting = new SampleApp(); txtName.Text = setting.myName; dtBirthday.Value = setting.myBirthday; labColor.BackColor = setting.sysColor; } private void button6_Click(object sender, EventArgs e) { //寫入設定值 SampleApp setting = new SampleApp(); setting.myName = txtName.Text; setting.myBirthday = dtBirthday.Value; setting.sysColor = labColor.BackColor; setting.Save(); }
PS1.
存檔之後,檢查 app.config 或 XXX.exe.config,為什麼資料都沒有改變呢?可是再執行一次程式,會發覺載入的資訊值卻是新的。為什麼?
這是因為,在 <userSettings> 這個區段底下的資訊,若被使用者變更後,會複製一份在 C:\Users\[username]\AppData\Local\Microsoft\.. 底下,檔名為 user.config 。 這時候,若再去變更 app.config 並不會發生什麼作用,因為關於 userSettings 的資訊,會以這個檔案優先讀取,除非它被刪除了,才會去讀取 app.config 裡面原始的設定值。 這也是為什麼<applicationSettings>這個區段是唯讀的原因,因為每個 User 只會讀取到屬於自已的 <userSettings> 部分。 若要在程式中變更全域的設定值,可以在公開的目錄底下建立custom config file。
下圖顯示, <userSettings> 這個區段真正的存放位置及內容.。
PS2.
所讀取的這個 user.config 檔案,是依據組件版號而異的,也就是,不同的版號,會自動建立一個目錄存放 user.config 檔。 所以一旦變更組件版號,就會讀取新的 user.config 檔。
利用 ApplicationSettings 儲存使用者習慣
在 WinForm 程式中,有時候我們會想記錄使用者上一次使用時的最後操作,方便下次開啟應用程式時自動載入前一次的設定。 例如下圖中,使用者必須透過 OpenFileDialog 設定操作的 Excel 檔案來源,這時我們可以利用 ApplicationSettings 快速的記錄下這個資訊,方便下次執行時自動載入。
要完成這個設定,你只要針對該控制項,新增一個 Text 屬性繫結(PropertyBinding)即可。步驟如下:
利用下拉選單中的功能,新增一個 ApplicationSettings 項目。
設定完成後,就會有一個 Text 的屬性繫結。
最後你必須找一個事件(例如:FormClosing),將上面設定儲存成預設值,等到程式下次執行時,就會自動載入這個預設值。
private void frmGPS_FormClosing(object sender, FormClosingEventArgs e) { Properties.Settings.Default.Save(); }
沒有留言:
張貼留言