在运行时

时间:2016-02-25 05:59:53

标签: c# .net configuration app-config configurationmanager

我需要在运行时修改<configuration><system.diagnostics>的{​​{1}}部分,以便我可以:

  1. app.config元素下添加CustomTraceListener,这需要特殊的<sharedListeners>,只能在运行时确定。

  2. initializeData共享侦听器添加到CustomTraceListener元素下的现有源。

  3. <source><listeners>保留到其他程序集,这些程序集从配置文件加载其跟踪源和侦听器配置。

  4. CustomTraceListener中的相关部分目前看起来像这样:

    app.config

    使用<system.diagnostics> <sources> <source name="mysource" switchName="..." switchType="..."> <listeners> <add name="console" /> <add name="customtracelistener" /> /// need to add new listener here </listeners> </source> </sources> <sharedListeners> <add name="console" type="..." initializeData="..." /> <add name="customtracelistener" type="..." initializeData="..."> /// need to add custom trace listener here <filter type="..." initializeData="Warning"/> /// with a filter </add> </sharedListeners> <switches> <add name="..." value="..." /> </switches> </system.diagnostics> 我可以轻松完成:

    ConfigurationManager

    当我这样做时,Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSection diagnostics = config.GetSection("system.diagnostics"); diagnostics类型。有趣的是,我无法将System.Diagnostics.SystemDiagnosticsSection转换为diagnostics类型,因为我无法在任何命名空间中找到它。无论如何,SystemDiagnosticsSection似乎没有任何方法可以用来将数据写入该部分。

    我也无法将其转换为ConfigurationSection,因为NameValueConfigurationCollection基类型为diagnostics。我听说过这种技术,但似乎我无法使用它。

    我是否必须恢复使用普通的XML来实现这一目标?我真的不喜欢重新发明轮子。

3 个答案:

答案 0 :(得分:3)

您可以通过app.exe.config找到ConfigurationManager文件的路径,然后将配置文件作为XDocument加载。

string configPath = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;

XDocument config = XDocument.Load(configPath);
XElement diagnostics = config.Descendants().FirstOrDefault(e => e.Name == "system.diagnostics");

if (diagnostics == default(XElement))
{
    /// <system.diagnostics> element was not found in config
}
else
{
    /// make changes within <system.diagnostics> here...
}

config.Save(configPath);

Trace.Refresh();  /// reload the trace configuration

完成所需的更改后,将XDocument保存回磁盘,然后调用Trace.Refresh()重新加载跟踪配置。

See MSDN regarding the Trace.Refresh method here

答案 1 :(得分:1)

对于经验,如果应用程序在受保护目录下部署了良好的安装过程,我会警告您从应用程序进行app.config更改,例如。 MS OS中的程序文​​件已激活UAC。

要更新配置文件,有时您需要一些管理员权限。

在Visual Studio / debug或某些测试程序下,所有这些都是正确运行的,在部署之后,在生产中,你可能会遇到一些问题......

答案 2 :(得分:0)

如果您对<configuration><system.diagnostics>进行直接更改 运行时app.config文件的一部分,需要重新启动应用程序或必须调用Trace.Refresh()才能使更改生效。

另一种选择是在应用程序启动时以编程方式添加TraceListeners,例如     Trace.Listeners.Add(new TextWriterTraceListener("output.log", "myListener"));

https://msdn.microsoft.com/en-us/library/sk36c28t(v=vs.110).aspx

要在问题中添加initializeData值的过滤器,您可以使用TraceListener.Filter属性

要跨应用程序共享设置,您可以使用configSource元素上的<system.diagnostics>属性,并将该元素放在单独的配置文件中。这样做的缺点是该文件需要与app.config位于同一文件夹中。因此,对一个文件的更改要么需要复制并粘贴到其他位置,要么以其他方式共享。

另一种方法是将包含跟踪侦听器信息的自定义配置文件保存在所有应用程序可以访问的位置,然后在每个应用程序中启动时加载文件并按上述方式配置跟踪侦听器。

更新

要在整个应用程序中共享日志记录,您可以创建一个实现单例模式的类,以返回您的TraceSource实例或包装您的日志记录活动。这样你就不必绕过同一个实例

public class Logger
{
    private static Logger _logger;
        private TraceSource _ts;

        private Logger()
        {
        // Configure TraceSource here as required, e.g.
            _ts = new TraceSource("StackOverflow", SourceLevels.All);
            _ts.Listeners.Add(new TextWriterTraceListener(@"c:\temp\tracefile.log"));
        }

        public static Logger Get()
        {
            if (_logger == null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void TraceInfo(string message)
        {
            _ts.TraceInformation(message);
            _ts.Flush();
        }
}

// To use
Logger.Get().TraceInfo("This is a trace message");

您可以对此进行扩展,然后封装您要记录的实际消息,以便执行日志记录的代码不知道具体内容,并且您只有一个位置可以定义您的事件,例如。

public void TraceApplicationStarting()
{
    _ts.TraceEvent(TraceEventType.Verbose, 1, "Application Starting");
}