I need to modify the <configuration><system.diagnostics>
section of an app.config
at runtime so that I can:
add a CustomTraceListener
under the <sharedListeners>
element, which requires special initializeData
that can only be ascertained at runtime.
add the CustomTraceListener
shared listener to an existing source under the <source><listeners>
element.
persist the CustomTraceListener
to other assemblies which load their trace source and listener configurations from the config file.
The relevant sections in app.config
looks something like this presently:
<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:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConfigurationSection diagnostics = config.GetSection("system.diagnostics");
And when I do this, diagnostics
is a System.Diagnostics.SystemDiagnosticsSection
type. Interestingly I can't cast diagnostics
to a SystemDiagnosticsSection
type because I can't find it within any namespace. Regardless, ConfigurationSection
doesn't seem to have any methods that I can use to write data into the section.
I also can't cast it to a NameValueConfigurationCollection
because diagnostics
base type is 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? 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
.
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.