如何在.net Windows应用程序中动态重新加载app.config?我需要动态地打开和关闭日志记录,而不仅仅是基于应用程序启动时的值。
ConfigurationManager.RefreshSection(“appSettings”)不起作用,我也尝试使用OpenExeConfiguration显式打开配置文件,但我总是在应用程序启动时获取缓存值,而不是当前值。
我接受了创建自定义配置部分的答案。作为旁注和愚蠢的错误 - 如果您从IDE运行,则更新app.config文件并期待更改是没有意义的。 Yuo必须修改bin \ debug文件夹中的.exe.config文件。卫生署!
答案 0 :(得分:24)
您可以按照您的说法刷新您自己的部分:
ConfigurationManager.RefreshSection("yoursection/subsection");
只需将日志记录true / false移动到某个部分,您就可以了。
答案 1 :(得分:7)
如果您使用的是log4Net,则可以按照自己的要求进行操作:
虽然可以将log4net配置设置添加到项目的app.config
或web.config
文件中,但最好将它们放在单独的配置文件中。除了可维护性的明显好处之外,它还有一个额外的好处,即log4net可以在配置文件上放置FileSystemWatcher
对象,以监控它何时更改并动态更新其设置。
要使用单独的配置文件,请将名为Log4Net.config的文件添加到项目中,并将以下属性添加到AssemblyInfo.cs文件中:
[assembly: log4net.Config.XmlConfigurator(ConfigFile="Log4Net.config", Watch = true)]
注意:对于Web应用程序,这假定Log4Net.config
驻留在Web根目录中。确保log4net.config
文件标记为“复制到输出” - >在“属性”中“始终复制”。
答案 2 :(得分:7)
以下是你可以放置的hack,这将使配置从磁盘读取。
您只需要在修改模式下保存配置文件,然后刷新它将使应用程序从磁盘读取文件。
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
答案 3 :(得分:2)
只需注意,在WinForms中,只要您使用Application.Start(new Form1())
代替System.Xml
,就可以在加载应用程序之前(System.Configuration.ConfigurationManager
之前)对app.config进行编程更改
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);
答案 4 :(得分:1)
我编写了这个实现来改变运行时的日志级别,并将新的阈值保留回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>
答案 5 :(得分:0)
除非您使用XML编写自己的配置文件阅读器,否则我认为没有办法做到这一点。为什么不根据配置文件设置在应用程序启动时打开或关闭日志记录,然后在程序运行时动态打开或关闭它?
答案 6 :(得分:0)
我想我在log4net文档中读到这是不可能的。
尝试登录可以使用filesystemwatcher
监视的外部日志文件更新:再次发现.. http://logging.apache.org/log4net/release/manual/configuration.html#.config%20Files
在运行时无法重新加载app.config。
答案 7 :(得分:0)
我建议使用另一个XML文件而不是app.config。您甚至可以在文件中查看更改,并在更改时自动重新加载。
答案 8 :(得分:0)
实际使用:
Application.restart();
对我来说非常好。
此致
豪尔赫
答案 9 :(得分:0)
我尝试使用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");
}