拿別人家的app.config讀取securityCryptographyConfiguration的設定來進行加解密
先前遇到了一個怪異的需求,A程式要去load B程式的設定檔,因為用EnterpriseLibary設定的加解密資訊在B程式的config上
感覺好像很一般般的功能,但是實際做下去才知道.net自身的ConfigurationManager都只能load自己程式的config
既使是用OpenExeConfiguration這個Method指定路徑把config loag進來,其實他還是與App A的config無關,純粹只是load進來
所以我們要動態的把load進來的config加入App A的config內
在此之前先提一下load config的方法
剛剛提到的OpenExeConfiguration他有一個多載參數是string,要你填路徑
但是特別注意這邊填的路徑,以現在範例是填B.exe,他會自動幫你變成B.exe.config
所以你如果給的路徑就已經是B.exe.config會變成B.exe.config.config然後就拿不到你想要的東西了,請特小心
那如果我沒有一個.exe給他參考,就可以跟我一樣使用EnterpriseLibary內的FileConfigurationSource來讀取指定的config
回到主題,怎把load進來的config加入App A的config內呢
如果你跟我一樣想把load進來的section加入
FileConfigurationSource configFile = new FileConfigurationSource( filePath );
Configuration mainConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None );
ConfigurationSection section = configFile.GetSection( "securityCryptographyConfiguration" );
mainConfig.Sections.Add( "securityCryptographyConfiguration", section );
你就會得到一個
Orz…這也沒錯
山不轉路轉,我自己建一個新的section把資料copy過來再加入總行吧
所以我把程式改了一下
FileConfigurationSource configFile = new FileConfigurationSource( filePath );
Configuration mainConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None );
CryptographySettings section = (CryptographySettings)configFile.GetSection( "securityCryptographyConfiguration" );
CryptographySettings newSection = new CryptographySettings();
newSection.DefaultHashProviderName = section.DefaultHashProviderName;
newSection.DefaultSymmetricCryptoProviderName = section.DefaultSymmetricCryptoProviderName;
foreach( HashProviderData data in section.HashProviders )
{
newSection.HashProviders.Add( new HashProviderData( data.Name, data.Type ));
}
foreach( SymmetricProviderData data in section.SymmetricCryptoProviders )
{
newSection.SymmetricCryptoProviders.Add( new SymmetricProviderData( data.Name, data.Type ) );
}
mainConfig.Sections.Add( "securityCryptographyConfiguration", newSection );
ok~~就能成功加入,真是太好了
不過離成功還遠的呢!!
首先是加入後記的config要Save()一下,所以最後還要加上mainConfig.Save();
否則其他組件要load config時是沒這新的section的
再來是雖然加入了加解密的section,但是在使用Cryptographer時他會賞你一個Excption說路徑錯誤
我嘗試了好多地方最後把config檔dump至檔案後發現原來是runtime的設定檔資訊不足
這是B.config的設定內容
這是我dump出來的內容
不用看全貌就知道少了一堆東西,不過在CryptographySettings是沒有這些缺失的資訊的
怎半勒,路不轉人轉.EnterpriseLibary內定義的Section都是繼續自SerializableConfigurationSection
所以可以把整個Section序列,然後再建一個新的反序列回來!!真是太聰明了我
/// <summary>
/// 讀取設定檔內的加密區段
/// </summary>
/// <param name="iConfig">原始加密設定區段</param>
private void LoadCryptographySection( CryptographySettings section )
{
StringBuilder output = new StringBuilder();
XmlWriterSettings wSettings = new XmlWriterSettings();
wSettings.Indent = true;
using( XmlWriter writer = XmlWriter.Create( output, wSettings ) )
{
section.WriteXml( writer );
}
CryptographySettings newSection = new CryptographySettings();
XmlReaderSettings rSetting = new XmlReaderSettings();
rSetting.CloseInput = true;
StringReader sr = new StringReader( output.ToString() );
using( XmlReader reader = XmlReader.Create( sr, rSetting ) )
{
newSection.ReadXml( reader );
}
sr.Close();
//將建立的區段附加至目前runtime的config檔內,一定要save其他地方才會讀到
//為了不重覆加入加密區段要先移除再加入
Configuration mainConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None );
mainConfig.Sections.Remove( cryptographyConfigurationName );
mainConfig.Sections.Add( cryptographyConfigurationName, newSection );
mainConfig.Save();
}
這樣就完成啦!!動態把B.exe.config的加解密區段load到A.exe來運行
而A.exe其實有沒有這個實體的A.exe.config都沒差