【问题标题】:Write appSettings in external file在外部文件中写入 appSettings
【发布时间】:2015-02-25 19:15:51
【问题描述】:

我有一个配置文件 app.exe.config 并且 appSettings 部分有这样的内容:

<configuration>
    <appSettings configSource="app.file.config" />
</configuration>

app.file.config 文件是这样的:

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
  <add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

我需要在运行时编辑 var1、var2 和 var3,我有这样的代码:

Configuration config = ConfigurationManager.OpenExeConfiguration("...path\app.exe);

config.AppSettings.SectionInformation.ConfigSource = "app.file.config";

config.AppSettings.Settings["var1"].Value = "value 11";
config.AppSettings.Settings["var2"].Value = "value 22";
config.AppSettings.Settings["var3"].Value = "value 33";
config.Save(ConfigurationSaveMode.Modified);

ConfigurationManager.RefreshSection("appSettings");

当我运行 config.Save.... 文件 app.file.config 有一个带有属性“file”的 appSettings 节点。此属性的值为 app.file.config

<appSettings file="app.file.config">
<add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

现在,如果我尝试加载配置文件,则会出现异常消息“无法识别的属性‘文件’。请注意,属性名称区分大小写。”在 app.file.config 中。

如果我手动删除文件属性,配置文件加载正常。

有什么想法吗?

保存配置文件时如何避免写入文件属性。

谢谢

【问题讨论】:

  • 从来没有这样做过,如果你省略 ConfigSource = "app.file.config"; 这行会发生什么
  • 肯尼,我不明白你的意思。请问,你能详细解释一下吗?
  • 删除代码时会发生什么 "config.AppSettings.SectionInformation.ConfigSource = "app.file.config";"
  • 您的第一个标签中有错字,对吧?因为你要关闭它。
  • 感谢 Vitor Canova。这是一个打字错误

标签: c# .net config


【解决方案1】:

使用外部配置文件对应用程序来说是透明的,

这部分没问题

</configuration>
    <appSettings configSource="app.file.config" />
</configuration>

还有这个:

<?xml version="1.0" encoding="utf-8" ?>

<appSettings>
  <add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

把你的代码改成这样:

Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
config.AppSettings.Settings["var1"].Value = "value 11";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");

引用外部配置文件对应用程序是透明的, 所以你不必直接调用它。您可以使用配置管理器中的默认 appSetting 部分。

祝你好运

【讨论】:

  • 嗨 Tomer Klein,您建议将设置存储在 app.exe.config 中,而不是 app.file.config 中。
【解决方案2】:

防止混淆的更完整答案:

设置:

  1. 名为“app”的命令行项目
  2. app.exe.config 文件,App.config:

    <appSettings file="App.Settings.config"></appSettings>
    
  3. 带有“复制到输出目录”=“始终复制”的 App.Settings.config 文件

    <?xml version="1.0" encoding="utf-8"?>
    <appSettings>
      <add key="test" value="OVERRIDDEN"/>
    </appSettings>
    
  4. 程序.cs:

    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Local Config sections");
            var exepath = (new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
            Configuration config = ConfigurationManager.OpenExeConfiguration(exepath);
    
            config.AppSettings.SectionInformation.ConfigSource = "App.Settings.config";
    
            Console.WriteLine("BEFORE[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine($"BEFORE[testExternalOnly]={config.AppSettings.Settings["testExternalOnly"]?.Value}");
    
            //to avoid: Error CS0266
            //Explicitly cast 'System.Configuration.AppSettingsSection'
            AppSettingsSection myAppSettings = (AppSettingsSection)config.GetSection("appSettings");
    
            myAppSettings.Settings["test"].Value = "NEW";
            if (!myAppSettings.Settings.AllKeys.Contains("testExternalOnly"))
                myAppSettings.Settings.Add("testExternalOnly", "NEWEXTERNAL");
    
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
    
            //Read updated config
            Console.WriteLine("AFTER[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine("AFTER[testExternalOnly]=" + config.AppSettings.Settings["testExternalOnly"].Value);
    
            Console.WriteLine("AFTER CONFIG EXTERNAL FILE: " + System.IO.File.ReadAllText("App.Settings.config"));
    
            Console.WriteLine("AFTER CONFIG FILE: " + System.IO.File.ReadAllText(System.AppDomain.CurrentDomain.FriendlyName + ".config"));
    
    
            //Shut current config
            config = null;
    
            //Open config
            config = ConfigurationManager.OpenExeConfiguration(exepath);
            config.AppSettings.SectionInformation.ConfigSource = "App.Settings.config";
    
            Console.WriteLine("AFTER[test]=" + config.AppSettings.Settings["test"].Value);
            Console.WriteLine("AFTER[testExternalOnly]=" + config.AppSettings.Settings["testExternalOnly"].Value);
    
            Console.WriteLine("AFTER CONFIG EXTERNAL FILE: " + System.IO.File.ReadAllText("App.Settings.config"));
    
            Console.WriteLine("AFTER CONFIG FILE: " + System.IO.File.ReadAllText(System.AppDomain.CurrentDomain.FriendlyName + ".config"));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.WriteLine("press the ENTER key to end");
        Console.ReadLine();
    
    }
    

这将导致 App.Settings.config 文件更新为在文件系统上:

<?xml version="1.0" encoding="utf-8"?>
<appSettings>
  <add key="test" value="NEW" />
  <add key="testExternalOnly" value="NEWEXTERNAL" />
</appSettings>

【讨论】:

  • 如果我理解正确,您的回答暗示没有解决方案?如果是这样,请查看接受的答案。
  • @Amessihel 您是否在新的 Framework4.8 控制台应用程序中对其进行了测试?你得到了什么结果?我的答案中包含了“TEST4”。如果您的测试代码不同且结果不同,我将非常乐意对其进行审核。
  • 我在 .NET 4.0 中使用 Visual Studio 2010 x86(32 位)对其进行了测试。 @J19 解决方案有效。
  • 原始答案已编辑,现在可以使用 Uri 作为 Exe 路径和 config.AppSettings.SectionInformation.ConfigSource = "App.Settings.config";
【解决方案3】:

终于找到了解决办法。

解决方案是将配置文件声明为:

<appSettings configSource="app.file.config">
<add key="var1" value="value 1" />
  <add key="var2" value="value 2" />
  <add key="var3" value="value 3" />
</appSettings>

从代码中

Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
AppSettingsSection myAppSettings = config.GetSection("appSettings")
myAppSettings.Settings["var1"].Value = "value 11";
config.Save(ConfigurationSaveMode.Modified);

请注意,我使用 GetSection("appSettings") 代替 config.AppSettings.Settings

感谢所有帮助 StackOverflow 的人。

【讨论】:

  • 从 Tomer Klein 的答案中窃取你自己,然后接受你自己的答案。
  • 嗨,Christopher Painter,这不完全一样。在我的场景中,关键点是“AppSettingsSection myAppSettings = config.GetSection("appSettings")”。使用 GetSection 是解决方案。感谢 Tomer Klein 的回答,但对我来说,我需要一些改变
  • @christoper-painter,@j19 实际上是在做某事。我认为他想在以编程方式保存设置时更新app.file.config 而不是app.exe.config。至少那是我想做的,configSource 属性而不是file 正是这样做的,请参阅stackoverflow.com/questions/6940004/…
  • 应该是最受好评的答案。这不公平。
  • @OzBob,其实我在测试这个解决方案的时候,没有用Application.ExecutablePath,而是System.Reflection.Assembly.GetExecutingAssembly().CodeBase。它返回一个 URI,所以我使用 new Uri(codebase).LocalPath 获取本地路径。我不喜欢单次使用实例化对象,但因为它每次执行一次就可以了。
猜你喜欢
  • 2012-07-31
  • 2013-09-20
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-26
  • 2016-01-11
  • 1970-01-01
相关资源
最近更新 更多