.NET Framework中应使用ConfigurationManager读取app.config,写入需调用OpenExeConfiguration并RefreshSection;禁用XML API直接操作,推荐JSON配置或Properties.Settings。

在 .NET Framework 应用程序中,app.config(编译后变为 [AppName].exe.config)是标准的客户端配置文件,用于存储连接字符串、应用设置、自定义配置节等。它本质是 XML 文件,但不能直接用 XmlDocument 或 XDocument 随意读写——因为运行时 .NET 会缓存配置,且写入需考虑权限、多线程、配置节只读性等限制。
读取 app.config 中的配置项
推荐使用 ConfigurationManager(.NET Framework)或 ConfigurationBuilder(.NET Core/5+)。本文聚焦传统 .NET Framework 场景:
-
读取
值 :用ConfigurationManager.AppSettings["Key"],例如:
代码中:string url = ConfigurationManager.AppSettings["ApiUrl"]; // 返回字符串 -
读取
:用 ConfigurationManager.ConnectionStrings["MyDb"],返回ConnectionStringSettings对象,其.ConnectionString属性才是实际连接字符串。 -
读取自定义配置节:需先定义类继承
ConfigurationSection,再在 config 中注册,最后用ConfigurationManager.GetSection("sectionName")获取强类型对象。
运行时修改 app.config 并保存(谨慎操作)
默认情况下,app.config 是只读的,且修改后不会自动生效于当前运行实例(已加载的配置不会刷新)。如确需写入(如保存用户偏好),应操作 运行时生成的 .config 文件(即 [AppName].exe.config),并注意以下要点:
- 必须使用
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)获取可写的Configuration对象; - 仅支持修改
和(其他节可能被标记为只读); - 调用
config.Save()后,需手动调用ConfigurationManager.RefreshSection("appSettings")才能让后续读取生效; - 写入操作需要对 config 文件所在目录有写权限(尤其在 Program Files 下常失败,建议避免部署到受限路径)。
示例(更新 appSettings):
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["Theme"].Value = "Dark";
config.Save();
ConfigurationManager.RefreshSection("appSettings"); // 刷新缓存
不推荐但常见误区:直接用 XML API 操作 app.config 文件
有人尝试用 XDocument.Load("app.config") 修改并保存——这看似可行,但存在严重问题:
- 修改的是源项目中的
app.config,而非运行时实际加载的[AppName].exe.config(后者在输出目录); - 绕过 .NET 配置系统,导致
ConfigurationManager缓存与磁盘文件不一致; - 无法触发配置刷新,新值对当前进程不可见;
- 多线程下易引发文件锁或写入冲突。
除非你明确知道自己在做什么(比如构建配置生成工具),否则不要这么做。
替代方案:更现代、更安全的做法
对于新项目或需要频繁读写配置的场景,建议迁移到更灵活的方式:
- 使用
System.Text.Json或Newtonsoft.Json管理独立 JSON 配置文件(如settings.json),完全自主控制读写逻辑; - 用户级设置可用
Properties.Settings.Default(可视化设计器生成),它会自动保存到%LocalAppData%下,无需权限且线程安全; - .NET Core/5+ 推荐统一用
IConfiguration+ConfigurationBuilder,支持 JSON、INI、环境变量等多种源,且天然支持重载(reloadOnChange: true)。
基本上就这些。核心原则是:尊重 .NET 配置系统的生命周期和缓存机制,别绕过它硬改 XML。
