.net 动态刷新 app.config

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/272097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:32:12  来源:igfitidea点击:

.net dynamically refresh app.config

.netapp-config

提问by

How do I dynamically reload the app.config in a .net Windows application? I need to turn logging on and off dynamically and not just based upon the value at application start.

如何在 .net Windows 应用程序中动态重新加载 app.config?我需要动态地打开和关闭登录,而不仅仅是基于应用程序启动时的值。

ConfigurationManager.RefreshSection("appSettings") does not work and I've also tried explicitly opening the config file using OpenExeConfiguration but I always get the cached value at application startup and not the current value.

ConfigurationManager.RefreshSection("appSettings") 不起作用,我也尝试使用 OpenExeConfiguration 显式打开配置文件,但我总是在应用程序启动时获取缓存值,而不是当前值。

I've accepted the answer of creating a custom configuration section. As a side note and foolish mistake - if you're running from the IDE there's no point in updating the app.config file and expecting changes. Yuo have to modify the .exe.config file in the bin\debug folder. Doh!

我已经接受了创建自定义配置部分的答案。作为旁注和愚蠢的错误 - 如果您从 IDE 运行,则更新 app.config 文件并期待更改毫无意义。您必须修改 bin\debug 文件夹中的 .exe.config 文件。哦!

采纳答案by Patrick Desjardins

You can refresh your ownsection the way you say:

你可以按照你说的方式刷新你自己的部分:

ConfigurationManager.RefreshSection("yoursection/subsection");

Just move a logging true/false into a section and you'll be fine.

只需将日志记录真/假移动到一个部分,你就会没事的。

回答by Mitch Wheat

If you are using log4Net, you can do what you asked:

如果您使用的是 log4Net,您可以按照您的要求进行操作:

Although it is possible to add your log4net configuration settings to your project's app.configor web.configfile, it is preferable to place them in a separate configuration file. Aside from the obvious benefit of maintainability, it has the added benefit that log4net can place a FileSystemWatcherobject on your config file to monitor when it changes and update its settings dynamically.

尽管可以将 log4net 配置设置添加到项目app.configweb.config文件中,但最好将它们放在单独的配置文件中。除了可维护性的明显好处之外,它还有一个额外的好处,即 log4net 可以FileSystemWatcher在您的配置文件中放置一个对象,以监视它何时更改并动态更新其设置。

To use a separate config file, add a file named Log4Net.config to your project and add the following attribute to your AssemblyInfo.cs file:

要使用单独的配置文件,请将名为 Log4Net.config 的文件添加到您的项目,并将以下属性添加到您的 AssemblyInfo.cs 文件:

[assembly: log4net.Config.XmlConfigurator(ConfigFile="Log4Net.config", Watch = true)]

Note: for web applications, this assumes Log4Net.configresides in the web root. Ensure the log4net.configfile is marked as “Copy To Output” -> “Copy Always” in Properties.

注意:对于 Web 应用程序,这假定Log4Net.config驻留在 Web 根目录中。确保log4net.config文件在属性中标记为“复制到输出”->“始终复制”。

回答by Ruchir

Following is the hack which you can put this will make config to read from disk.

以下是您可以放置​​的 hack,这将使配置从磁盘读取。

You just need to save the config file in Modified Mode and then refresh this will make application to read the file agian from the disk.

您只需要在修改模式下保存配置文件,然后刷新,这将使应用程序再次从磁盘读取文件。

ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");

回答by foson

Just a note, in WinForms, you can make programmatic changes to your app.config before your application loads (before Application.Start(new Form1())), as long as you use System.Xmlinstead of System.Configuration.ConfigurationManager

请注意,在 WinForms 中,您可以在应用程序加载之前(之前Application.Start(new Form1()))对您的 app.config 进行编程更改,只要您使用System.Xml而不是System.Configuration.ConfigurationManager

string configFile = Application.ExecutablePath + ".config";  //c:\path\exename.exe.config
XmlDocument xdoc = new XmlDocument();
xdoc.Load(configFile);
XmlNode node = xdoc.SelectSingleNode("/configuration/appSettings/add[@key='nodeToChange']/@value");
node.Value = "new value";
File.WriteAllText(setFile, xdoc.InnerXml);

回答by froeschli

I wrote this implementation to change the log level at runtime and persist the new treshold back to the app.config (actually the Application.exe.config).

我编写了这个实现来在运行时更改日志级别并将新的阈值保留回 app.config(实际上是 Application.exe.config)。

The interface:

界面:

internal interface ILoggingConfiguration
{
  void SetLogLevel(string level);

  string GetLogLevel();
}

The implementation:

实施:

internal sealed class LoggingConfigurationImpl : ILoggingConfiguration
{
  #region Members

  private static readonly ILog _logger = 
    ObjectManager.Common.Logger.GetLogger();
  private const string DEFAULT_NAME_SPACE = "Default.Name.Space";

  #endregion

  #region Implementation of ILoggingConfiguration

  public void SetLogLevel(string level)
  {
    Level threshold = Log4NetUtils.ConvertToLevel(level);
    ILoggerRepository[] repositories = LogManager.GetAllRepositories();

    foreach (ILoggerRepository repository in repositories)
    {
      try
      {
        SetLogLevelOnRepository(repository, threshold);
      }
      catch (Exception ex)
      {
        _logger.ErrorFormat("Exception while changing log-level: {0}", ex);
      }
    }
    PersistLogLevel(level);
  }

  public string GetLogLevel()
  {
    ILoggerRepository repository = LogManager.GetRepository();
    Hierarchy hierarchy = (Hierarchy) repository;
    ILogger logger = hierarchy.GetLogger(DEFAULT_NAME_SPACE);
    return ((Logger) logger).Level.DisplayName;
  }

  private void SetLogLevelOnRepository(ILoggerRepository repository,
                                       Level threshold)
  {
    repository.Threshold = threshold;
    Hierarchy hierarchy = (Hierarchy)repository;
    ILogger[] loggers = hierarchy.GetCurrentLoggers();
    foreach (ILogger logger in loggers)
    {
      try
      {
        SetLogLevelOnLogger(threshold, logger);
      }
      catch (Exception ex)
      {
        _logger.ErrorFormat("Exception while changing log-level for 
            logger: {0}{1}{2}", logger, Environment.NewLine, ex);
      }
    }
  }

  private void SetLogLevelOnLogger(Level threshold, ILogger logger)
  {
    ((Logger)logger).Level = threshold;
  }

  private void PersistLogLevel(string level)
  {
    XmlDocument config = new XmlDocument();
    config.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    string xpath =
      String.Format("configuration/log4net/logger[@name='{0}']/level",
        DEFAULT_NAME_SPACE);
    XmlNode rootLoggerNode = config.SelectSingleNode(xpath);

    try
    {
      rootLoggerNode.Attributes["value"].Value = level;
      config.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

      ConfigurationManager.RefreshSection("log4net");
    }
    catch(Exception ex)
    {
      _logger.ErrorFormat("error while persisting new log-level: {0}", ex);
    }
  }

  #endregion
}

The helper class Log4NetUtils:

帮助类 Log4NetUtils:

public sealed class Log4NetUtils
{
  private static readonly ILoggerRepository _loggerRepository =
     LoggerManager.GetAllRepositories().First();

  public static Level ConvertToLevel(string level)
  {
    return _loggerRepository.LevelMap[level];
  }
}

The XAML code:

XAML 代码:

<ComboBox Name="cbxLogLevel" Text="{Binding LogLevel}">
  <ComboBoxItem Content="DEBUG" />
  <ComboBoxItem Content="INFO" />
  <ComboBoxItem Content="WARN" />
  <ComboBoxItem Content="ERROR" />
</ComboBox>
<Button Name="btnChangeLogLevel" 
        Command="{Binding SetLogLevelCommand}"
        CommandParameter="{Binding ElementName=cbxLogLevel, Path=Text}" >
            Change log level
</Button>

回答by Sudhanshu Mishra

I have tried using the RefreshSection method and got it to work using the following code sample:

我尝试使用 RefreshSection 方法并使用以下代码示例使其工作:

class Program
    {
        static void Main(string[] args)
        {
            string value = string.Empty, key = "mySetting";
            Program program = new Program();

            program.GetValue(program, key);
            Console.WriteLine("--------------------------------------------------------------");
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        /// <summary>
        /// Gets the value of the specified key from app.config file.
        /// </summary>
        /// <param name="program">The instance of the program.</param>
        /// <param name="key">The key.</param>
        private void GetValue(Program program, string key)
        {
            string value;
            if (ConfigurationManager.AppSettings.AllKeys.Contains(key))
            {
                Console.WriteLine("--------------------------------------------------------------");
                Console.WriteLine("Key found, evaluating value...");
                value = ConfigurationManager.AppSettings[key];
                Console.WriteLine("Value read from app.confg for Key = {0} is {1}", key, value);
                Console.WriteLine("--------------------------------------------------------------");

                //// Update the value
                program.UpdateAppSettings(key, "newValue");
                //// Re-read from config file
                value = ConfigurationManager.AppSettings[key];
                Console.WriteLine("New Value read from app.confg for Key = {0} is {1}", key, value);
            }
            else
            {
                Console.WriteLine("Specified key not found in app.config");
            }
        }

        /// <summary>
        /// Updates the app settings.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        public void UpdateAppSettings(string key, string value)
        {
            Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            if (configuration.AppSettings.Settings.AllKeys.Contains(key))
            {
                configuration.AppSettings.Settings[key].Value = value;
            }

            configuration.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

回答by Sudhanshu Mishra

Actually using an:

实际上使用:

Application.restart();

Application.restart();

Has worked pretty good for me.

对我来说效果很好。

Regards

问候

Jorge

乔治

回答by MusiGenesis

I don't think there's any way to do this, unless you write your own config file reader using XML. Why not just turn logging on or off at the start of your app based on the config file setting, and then just turn it on or off dynamically while the program is running?

我认为没有任何方法可以做到这一点,除非您使用 XML 编写自己的配置文件阅读器。为什么不根据配置文件设置在应用程序启动时打开或关闭登录,然后在程序运行时动态打开或关闭它?

回答by Tigraine

I think I read in the log4net documentation that this is not possible.

我想我在 log4net 文档中读到这是不可能的。

Try having the logging in an external logfile that can be watched with a filesystemwatcher

尝试在外部日志文件中进行日志记录,该文件可以使用文件系统观察器进行监视

Update: Found it again.. http://logging.apache.org/log4net/release/manual/configuration.html#.config%20Files

更新:再次找到它.. http://logging.apache.org/log4net/release/manual/configuration.html#.config%20Files

There is no way to reload the app.config during runtime.

无法在运行时重新加载 app.config。

回答by eduesing

I would recommend using another XML file and not app.config. You could even watch the file for changes and automatically reload it when it changes.

我建议使用另一个 XML 文件而不是 app.config。你甚至可以观察文件的变化,并在它发生变化时自动重新加载它。