您的位置:首页 > 移动开发

配置文件——App.config文件读取和修改

2017-03-15 14:39 841 查看
[csharp] view
plain copy

 print?





using System;  

using System.Configuration;  

using System.Reflection;  

using System.Xml;  

  

namespace Jurassic.Sooil.Model.IOModel  

{  

    public class AppConfigHelper  

    {  

        public static string GetValueByKey(string key)  

        {  

            return ConfigurationManager.AppSettings[key];  

        }  

        public static void ModifyAppSettings(string strKey, string value)  

        {  

            var doc = new XmlDocument();  

            //获得配置文件的全路径    

            var strFileName = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;  

            doc.Load(strFileName);  

  

            //找出名称为“add”的所有元素    

            var nodes = doc.GetElementsByTagName("add");  

            for (int i = 0; i < nodes.Count; i++)  

            {  

                //获得将当前元素的key属性    

                var xmlAttributeCollection = nodes[i].Attributes;  

                if (xmlAttributeCollection != null)  

                {  

                    var att = xmlAttributeCollection["key"];  

                    if (att == null) continue;  

                    //根据元素的第一个属性来判断当前的元素是不是目标元素    

                    if (att.Value != strKey) continue;  

                    //对目标元素中的第二个属性赋值    

                    att = xmlAttributeCollection["value"];  

                    att.Value = value;  

                }  

                break;  

            }  

            //保存上面的修改    

            doc.Save(strFileName);  

            ConfigurationManager.RefreshSection("appSettings");  

        }  

    }  

}  

事实证明这种做法是不可行的。虽然程序运行时的值已经被修改。但是打开app.config查看,会看到值仍然没有被改动。如果重启程序,就会使用以前的旧值。用这种方法只可以读取值。不能写入或者修改值。

注意,正确的做法是,把配置文件按照普通的xml文件来进行修改,否则,经常出现的问题就是你所修改的东西其实最后根本没有写入文件!最后还是修改失败!

当作普通的xml文件读取的话,首先就要知道怎么寻找文件的路径。我们知道一般配置文件就在跟可执行exe文件在同一目录下,且仅仅在名称后面添加了一个.config 因此,可以用Application.ExecuteablePath+".cofig"的方式来获得,不过更加推荐使用AppDomain.CurrentDomain.SetupInformation.ConfigurationFile这句话来直接获取当前程序的配置文件的位置,具体原因,后面再叙述。

现在回过头还是看上面的这个函数,看它的最后一行,它的作用是什么?

查找msdn文档可以发现微软出于性能考虑,对配置文件App.config采用了缓存策略,因此,尽管上面的函数确实在磁盘文件中修改了节点的值,当时,当用前面的那个函数读取的时候,会依然得到原来的那个值,仿佛没有修改一样!所以,必须使用这么句话,进行一遍刷新,强制要求程序下一次读取的时候,从磁盘文件读取!

好了,现在使用Visual Studio写C#程序的童鞋应该都遇到了一个蛋疼的问题,就是在debug时,明明在程序中修改了配置文件,可是下次重新执行程序的时候,发现程序根本没有发生变化,打开与exe文件相对应的config文件查看,发现文件根本没有变化!!!!明明就是当作xml文件来操作的,怎么会这样?!

其实这就涉及VS的运行机制问题了,细心的童鞋会在exe文件的同目录下,发现有一个与之对应的vshost.exe,以及vshost.exe.config 文件,当打开这里的这个config文件后会发现,在这里面的xml文件的值发生了变化!对滴~VS无论在Debug还是Release下,运行的程序都是这个带有vshost的程序,修改的也是这个程序对应的config。当程序刚刚启动的时候,却是读取的原来与exe文件对应的config文件,将这个config文件内容替换原来与vshost.exe对应的config里面内容,这也就是为什么每次重新开程序后恢复原状的原因。

由于程序在VS里面调试的时候,运行的程序与直接去bin文件夹运行的程序不一样,所以,更推荐使用AppDomain.CurrentDomain.SetupInformation.ConfigurationFile来获取当前运行程序的配置文件。

用了各种方法 ,还是无法修改App.config的内容,虽然vshost.exe.config  确实修改。但是下一次启动读的还是原来的config,并且还替换了已经修改的vshost.exe.config 

怎么办,继续寻寻觅觅……

最终采取的方案如下:

[csharp] view
plain copy

 print?





public class AppConfigHelper  

 {  

     public static string GetValueByKey(string key)  

     {  

         ConfigurationManager.RefreshSection("appSettings");  

         return ConfigurationManager.AppSettings[key];  

     }  

     public static void ModifyAppSettings(string strKey, string value)  

     {  

         //获得配置文件的全路径    

         var assemblyConfigFile = Assembly.GetEntryAssembly().Location;  

         var appDomainConfigFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;  

         ChangeConfiguration(strKey, value, assemblyConfigFile);  

         ModifyAppConfig(strKey, value, appDomainConfigFile);  

     }  

  

     private static void ModifyAppConfig(string strKey, string value, string configPath)  

     {  

         var doc = new XmlDocument();  

         doc.Load(configPath);  

  

         //找出名称为“add”的所有元素    

         var nodes = doc.GetElementsByTagName("add");  

         for (int i = 0; i < nodes.Count; i++)  

         {  

             //获得将当前元素的key属性    

             var xmlAttributeCollection = nodes[i].Attributes;  

             if (xmlAttributeCollection != null)  

             {  

                 var att = xmlAttributeCollection["key"];  

                 if (att == null) continue;  

                 //根据元素的第一个属性来判断当前的元素是不是目标元素    

                 if (att.Value != strKey) continue;  

                 //对目标元素中的第二个属性赋值    

                 att = xmlAttributeCollection["value"];  

                 att.Value = value;  

             }  

             break;  

         }  

  

         //保存上面的修改    

         doc.Save(configPath);  

         ConfigurationManager.RefreshSection("appSettings");  

     }  

  

     public static void ChangeConfiguration(string key, string value, string path)  

     {  

         var config = ConfigurationManager.OpenExeConfiguration(path);  

         config.AppSettings.Settings.Remove(key);  

         config.AppSettings.Settings.Add(key, value);  

         config.Save(ConfigurationSaveMode.Modified);  

         ConfigurationManager.RefreshSection("appSettings");  

     }  

 }  

虽说 app.config文件 还是无法看到修改,但是程序运行的时候实际调用的两个文件(vshost.exe.config和exe.config  )都被修改了,这样每次启动
配置文件里的内容也都是最新的,只不过如果你的程序重新生成的话,两个文件就会被app.config的内容覆盖。

仅仅是调式阶段会有一些不方便,但是一旦打包,就能够很好的使用,每次都能修改配置文件内容,并读取到最新的内容。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: