我需要在运行时修改<configuration><system.diagnostics>
的{{1}}部分,以便我可以:
在app.config
元素下添加CustomTraceListener
,这需要特殊的<sharedListeners>
,只能在运行时确定。
将initializeData
共享侦听器添加到CustomTraceListener
元素下的现有源。
将<source><listeners>
保留到其他程序集,这些程序集从配置文件加载其跟踪源和侦听器配置。
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来实现这一目标?我真的不喜欢重新发明轮子。
答案 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()
重新加载跟踪配置。
答案 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");
}