.net динамически обновлять app.config

Как мне динамически перезагружать app.config в приложении Windows .net? Мне нужно динамически включать и отключать вход в систему, а не только в зависимости от значения при запуске приложения.

ConfigurationManager.RefreshSection ("appSettings") не работает, и я также пробовал явно открыть файл конфигурации с помощью OpenExeConfiguration, но я всегда получаю кешированное значение при запуске приложения, а не текущее значение.

Я принял ответ о создании раздела настраиваемой конфигурации. В качестве побочного примечания и глупой ошибки - если вы работаете из IDE, нет смысла обновлять файл app.config и ожидать изменений. Вам нужно изменить файл .exe.config в папке bin \ debug. Дох!


person Community    schedule 07.11.2008    source источник
comment
Используя .NET 4.0 и VS2013update4, у меня все работает нормально. то есть я просто вызываю ConfigurationManager.RefreshSection (appSettings) после изменения файла app.config на диске, и он правильно перезагружает настройки.   -  person dodgy_coder    schedule 26.02.2015
comment
Отсутствует небольшая деталь: после того, как вы выполните вещь ConfigurationManager.RefreshSection (appSettings), вам нужно перезагрузить конфигурацию = ConfigurationManager.OpenExeConfiguration (Application.ExecutablePath)   -  person Perdi Estaquel    schedule 27.04.2016


Ответы (10)


Вы можете обновить свой раздел, сказав:

ConfigurationManager.RefreshSection("yoursection/subsection");

Просто переместите логирование true / false в раздел, и все будет в порядке.

person Patrick Desjardins    schedule 07.11.2008

Если вы используете log4Net, вы можете сделать то, что просили:

Хотя можно добавить параметры конфигурации log4net в файл app.config или web.config вашего проекта, желательно поместить их в отдельный файл конфигурации. Помимо очевидного преимущества ремонтопригодности, у него есть дополнительное преимущество, заключающееся в том, что log4net может размещать объект FileSystemWatcher в вашем файле конфигурации для отслеживания его изменений и динамического обновления своих настроек.

Чтобы использовать отдельный файл конфигурации, добавьте в проект файл с именем Log4Net.config и добавьте следующий атрибут в свой файл AssemblyInfo.cs:

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

Примечание: для веб-приложений предполагается, что Log4Net.config находится в корневом веб-каталоге. Убедитесь, что файл log4net.config помечен как «Копировать в вывод» -> «Всегда копировать» в свойствах.

person Mitch Wheat    schedule 07.11.2008

Ниже приведен хак, который вы можете использовать, чтобы конфигурация читалась с диска.

Вам просто нужно сохранить файл конфигурации в модифицированном режиме, а затем обновить, это заставит приложение читать файл с диска.

ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
person Ruchir    schedule 31.08.2010
comment
@DanielAllenLangdon: (Поздний ответ, я знаю) Я пробовал вызвать метод Save с предложенным параметром, и он работает - person Sudhanshu Mishra; 11.07.2012
comment
Я добавил код, который использовал в качестве ответа. на всякий случай кто-то захочет взглянуть - person Sudhanshu Mishra; 11.07.2012

Обратите внимание: в WinForms вы можете вносить программные изменения в свой app.config до загрузки вашего приложения (до Application.Start(new Form1())), если вы используете 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);
person foson    schedule 14.04.2009

Я написал эту реализацию, чтобы изменить уровень журнала во время выполнения и сохранить новый порог обратно в app.config (на самом деле Application.exe.config).

Интерфейс:

internal interface ILoggingConfiguration
{
  void SetLogLevel(string level);

  string GetLogLevel();
}

Реализация:

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
}

Вспомогательный класс Log4NetUtils:

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

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

Код 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>
person froeschli    schedule 27.07.2011

Я не думаю, что есть какой-либо способ сделать это, если только вы не напишете свой собственный читатель конфигурационных файлов с использованием XML. Почему бы просто не включить или выключить ведение журнала при запуске приложения в зависимости от настроек файла конфигурации, а затем просто включить или выключить его динамически во время работы программы?

person MusiGenesis    schedule 07.11.2008

Я думаю, что прочитал в документации log4net, что это невозможно.

Попробуйте вести журнал во внешнем файле журнала, который можно отслеживать с помощью filesystemwatcher.

Обновление: нашел снова .. http://logging.apache.org/log4net/release/manual/configuration.html#.config%20Files

Невозможно перезагрузить app.config во время выполнения.

person Tigraine    schedule 07.11.2008
comment
log4net не позволяет динамически включать или отключать вход в систему? - person MusiGenesis; 07.11.2008
comment
Log4net позволяет это. Но если ваша конфигурация log4net установлена ​​в вашем application.config, тогда нет возможности изменить эту конфигурацию во время выполнения. - person Tigraine; 11.11.2008

Я бы рекомендовал использовать другой XML-файл, а не app.config. Вы даже можете следить за изменениями в файле и автоматически перезагружать его при изменении.

person eduesing    schedule 07.11.2008

Фактически используя:

Application.restart ();

У меня сработало довольно хорошо.

С Уважением

Хорхе

person Community    schedule 29.07.2009
comment
Application.restart () не будет работать, если у вас есть переменные, которые должны сохранять свое состояние. Кроме того, я создал новое окно с задержкой около 10-15 секунд после закрытия старого, так что это определенно не идеальное решение. - person adam_0; 17.07.2010

Я пробовал использовать метод 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");
        }
person Sudhanshu Mishra    schedule 11.07.2012