[英]Modify app.config <system.diagnostics> section at runtime
I need to modify the <configuration><system.diagnostics>
section of an app.config
at runtime so that I can: 我需要在运行时修改
app.config
的<configuration><system.diagnostics>
部分,以便我可以:
add a CustomTraceListener
under the <sharedListeners>
element, which requires special initializeData
that can only be ascertained at runtime. 在
<sharedListeners>
元素下添加一个CustomTraceListener
,这需要特殊的initializeData
,只能在运行时确定。
add the CustomTraceListener
shared listener to an existing source under the <source><listeners>
element. 将
CustomTraceListener
共享侦听器添加到<source><listeners>
元素下的现有源。
persist the CustomTraceListener
to other assemblies which load their trace source and listener configurations from the config file. 将
CustomTraceListener
持久CustomTraceListener
到其他程序集,这些程序集从配置文件加载其跟踪源和侦听器配置。
The relevant sections in app.config
looks something like this presently: 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>
Using ConfigurationManager
I can easily do: 使用
ConfigurationManager
我可以轻松地做到:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection diagnostics = config.GetSection("system.diagnostics");
And when I do this, diagnostics
is a System.Diagnostics.SystemDiagnosticsSection
type. 当我这样做时,
diagnostics
是System.Diagnostics.SystemDiagnosticsSection
类型。 Interestingly I can't cast diagnostics
to a SystemDiagnosticsSection
type because I can't find it within any namespace. 有趣的是,我无法将
diagnostics
转换为SystemDiagnosticsSection
类型,因为我无法在任何命名空间中找到它。 Regardless, ConfigurationSection
doesn't seem to have any methods that I can use to write data into the section. 无论如何,
ConfigurationSection
似乎没有任何方法可以用来将数据写入该部分。
I also can't cast it to a NameValueConfigurationCollection
because diagnostics
base type is ConfigurationSection
. 我也无法将其转换为
NameValueConfigurationCollection
因为diagnostics
基类型是ConfigurationSection
。 I heard about this technique but it seems I can't use it. 我听说过这种技术,但似乎我无法使用它。
Do I have to revert to using plain-old XML to accomplish this? 我是否必须恢复使用普通的XML来实现这一目标? I really don't like reinventing the wheel.
我真的不喜欢重新发明轮子。
You can locate the path to the app.exe.config
file through the ConfigurationManager
, then load the config file as an XDocument
. 您可以通过
ConfigurationManager
找到app.exe.config
文件的路径,然后将配置文件作为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
Once the required changes are made, save the XDocument
back to disk, and call Trace.Refresh()
to reload the trace configuration. 完成所需的更改后,将
XDocument
保存回磁盘,并调用Trace.Refresh()
以重新加载跟踪配置。
See MSDN regarding the Trace.Refresh
method here . 有关
Trace.Refresh
方法,请参阅MSDN 。
For experience i would warn you to make app.config changes from application if the app is deployed with a good install procedure under protected directories, eg. 对于经验,如果应用程序在受保护目录下部署了良好的安装过程,我会警告您从应用程序进行app.config更改,例如。 Program files in MS OS with UAC activated.
MS OS中的程序文件已激活UAC。
To update config files sometimes you need some admin privileges. 要更新配置文件,有时您需要一些管理员权限。
The Bad thing is than all run correctly under visual studio / debug or some test procedure, after deploy, in production,you may have some issue... 糟糕的事情是在视觉工作室/调试或某些测试程序下正确运行,在部署之后,在生产中,您可能会遇到一些问题......
If you make direct changes to the <configuration><system.diagnostics>
section of the app.config
file at run time, the app needs to be restarted or Trace.Refresh()
must be called to have the changes take effect. 如果在运行时直接更改
app.config
文件的<configuration><system.diagnostics>
部分,则需要重新启动应用程序或必须调用Trace.Refresh()
才能使更改生效。
Another option is to programmatically add TraceListeners at application start-up, eg Trace.Listeners.Add(new TextWriterTraceListener("output.log", "myListener"));
另一种选择是在应用程序启动时以编程方式添加TraceListeners,例如
Trace.Listeners.Add(new TextWriterTraceListener("output.log", "myListener"));
see https://msdn.microsoft.com/en-us/library/sk36c28t(v=vs.110).aspx . 请参阅https://msdn.microsoft.com/en-us/library/sk36c28t(v=vs.110).aspx 。
To add a filter with the initializeData
value as in your question you can use the TraceListener.Filter
property 要在问题中添加具有
initializeData
值的过滤器,可以使用TraceListener.Filter
属性
To share settings across applications you can use the configSource
property on the <system.diagnostics>
element and put that element in a separate config file. 要跨应用程序共享设置,可以使用
<system.diagnostics>
元素上的configSource
属性,并将该元素放在单独的配置文件中。 The downside of this is that the file needs to be in the same folder as the app.config. 这样做的缺点是该文件需要与app.config位于同一文件夹中。 So a change to one file would either need to be copied and pasted to other locations or shared in some other way.
因此,对一个文件的更改要么需要复制并粘贴到其他位置,要么以其他方式共享。
An alternative would be to save a custom config file containing the trace listener information at a location all apps can access and then in each app load the file at start-up and configure the trace listeners as above. 另一种方法是在所有应用程序可以访问的位置保存包含跟踪侦听器信息的自定义配置文件,然后在每个应用程序中启动时加载文件并按上述方式配置跟踪侦听器。
Update 更新
To share logging throughout your application you could create a class that implements the singleton pattern to return your TraceSource
instance or to wrap your logging activities. 要在整个应用程序中共享日志记录,您可以创建一个实现单例模式的类,以返回
TraceSource
实例或包装日志记录活动。 This way you don't have to pass round the same instance 这样您就不必传递相同的实例
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");
You could extend this to then encapsulate the actual messages you want to log so that the code doing the logging doesn't know the specifics and you have just one place where your events are defined, eg 您可以对此进行扩展,然后封装您要记录的实际消息,以便执行日志记录的代码不知道具体内容,并且您只有一个位置可以定义事件,例如
public void TraceApplicationStarting()
{
_ts.TraceEvent(TraceEventType.Verbose, 1, "Application Starting");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.