昨天遇到了很奇怪的一个 bug, 具体描述如下:
这个系统是 c/s 架构的针对多个工厂做的资材管理系统, 由于有很多个工厂, 每个工厂都有自己的服务器. 所以需要动态的改变连接字符串去链接不同的服务器.
由于这个连接字符串放在了 App.config 文件中, 所以公司上一个开发人员设置为, 当选择不同公司时会让程序关闭然后去更新配置文件. 近来由于公司要求, 不想让程序重启然后去改变配置文件.
原本的解决方案是当下拉框发生改变的时候, 重新向新的服务器发送请求获取数据.
但是出现了一个问题, 就是项目中所用的 dataset 中绑定的连接字符串不会实时获取新的连接字符串.
也就是程序中对 App.config 的修改没有立马产生作用.
经过一上午的测试与查找资料, 找到问题发生的原因及解决方案.
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");
- }
关于宿主进程的详细测试如下:
用宿主进程和不用宿主进程进行调试的一些差异
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, 它将返回该应用程序名.
来源: http://www.bubuko.com/infodetail-2855112.html