昨天遇到了很奇怪的一个bug,具体描述以下:安全
这个系统是c/s架构的针对多个工厂作的资材管理系统,因为有不少个工厂,每一个工厂都有本身的服务器。因此须要动态的改变链接字符串去连接不一样的服务器。服务器
因为这个链接字符串放在了app.config文件中,因此公司上一个开发人员设置为,当选择不一样公司时会让程序关闭而后去更新配置文件。近来因为公司要求,不想让程序重启而后去改变配置文件。架构
本来的解决方案是当下拉框发生改变的时候,从新向新的服务器发送请求获取数据。app
可是出现了一个问题,就是项目中所用的dataset中绑定的链接字符串不会实时获取新的链接字符串。测试
也就是程序中对app.config的修改没有立马产生做用。
通过一上午的测试与查找资料,找到问题发生的缘由及解决方案。spa
VS2005之后,会默认生成VS宿主进程,在项目的属性 的调试项目下的一个选项。
当启用这个功能后,在程序中对app.config所作的操做不会实时改变,而是修改*.exe.config和*.Vhost.Config,并不会直接修改App.config设计
解决方法是禁用掉这一个选项,并在修改app.config方法中添加对配置文件的刷新调试
/// <summary> /// 修改 app.config 中 connectionStrings 的方法 /// </summary> /// <param name="AppKey"></param> /// <param name="AppValue"></param> public void SetConfigValue(string keyName, string conStr) { XmlDocument xDoc = new XmlDocument(); //获取可执行文件的路径和名称 xDoc.Load(System.Windows.Forms.Application.ExecutablePath + ".config"); XmlNode xNode; XmlElement xElem1; XmlElement xElem2; xNode = xDoc.SelectSingleNode("//connectionStrings"); xElem1 = (XmlElement)xNode.SelectSingleNode("//add[@name='" + keyName + "']"); if (xElem1 != null) xElem1.SetAttribute("connectionString", conStr); else { xElem2 = xDoc.CreateElement("add"); xElem2.SetAttribute("name", keyName); xElem2.SetAttribute("connectionString", conStr); xNode.AppendChild(xElem2); } xDoc.Save(System.Windows.Forms.Application.ExecutablePath + ".config"); ConfigurationManager.RefreshSection("connectionStrings"); }
关于宿主进程的详细测试以下:code
用宿主进程和不用宿主进程进行调试的一些差别orm
1) 部分信任调试和 Click-Once 安全
部分信任调试须要宿主进程。若是禁用宿主进程,部分信任调试将不工做,即便在“项目属性”的“安全”页上启用了部分信任安全。
2) 设计时表达式计算
设计时表达式始终使用宿主进程。若是在“项目属性”中禁用宿主进程,则禁用了类库项目的设计时表达式计算。对于其余项目类型,不由用设计时表达式计算。相反,Visual Studio 启动实际可执行文件,并将它用于不用宿主进程的设计时计算。这种差别可能产生不一样的结果。
3) AppDomain.CurrentDomain.FriendlyName 差别
AppDomain.CurrentDomain.FriendlyName 依据是否启用宿主进程返回不一样的结果。若是启用宿主进程时调用 AppDomain.CurrentDomain.FriendlyName,它将返回 app_name.vhost.exe。若是禁用宿主进程时调用它,它将返回 app_name.exe。
4) Assembly.GetCallingAssembly().FullName 差别
Assembly.GetCallingAssembly().FullName 依据是否启用宿主进程返回不一样的结果。若是启用宿主进程时调用 Assembly.GetCallingAssembly().FullName,它将返回 mscorlib。若是禁用宿主进程时调用 Assembly.GetCallingAssembly().FullName,它将返回该应用程序名。