My Development KB

Odds and ends related to software development

Controlling .NET System.Net Tracing via the Registry

Posted by Ben G on June 29, 2009

We have a Click Once-deployed project that I wanted to set up for instrumentation and tracing. Because the project deploys to a rather obscure folder defined by Click Once, it makes it a very difficult thing to have our support personnel troubleshoot issues in the field by applying a modified app.config file that enables tracing.

I set up our internal trace sources programmatically to read the switch value from the registry, which worked fine. However, when it came to configuring the System.Net trace sources, I ran into problems. After a lot of searching it appears impossible to gain access to those system trace sources without using some shady reflection techniques which I’m not comfortable with in a production environment. Without access to those TraceSource objects, it is impossible to programmitically add my own switches and listeners.

My eventual solution was to configure the System.Net trace sources in the app.config file, but use a custom switch that reads its value from the registry. It took me a bit to figure out how to do this, so I’m reposting it here:

My custom switch looks like this:


Public Class RegistrySwitch
    Inherits SourceSwitch

    Public Sub New(ByVal name As String)
        MyBase.New(name)
        Me.Value = GetSwitchValue()
    End Sub

    Public Sub New(ByVal name As StringByVal value As String)
        MyBase.New(name)
        Me.Value = GetSwitchValue()
    End Sub

    Private Shared Function GetSwitchValue()
        Dim switchValue As String = GetRegistryValue("TracingLevel""Off")

        Select Case switchValue
            Case "True""1""-1""On"
                switchValue = "All"
            Case "0""False"
                switchValue = "Off"
        End Select

        Return switchValue
    End Function

End
 Class

The GetRegistryValue function (code not shown) simply reads the specified value from our product’s key in the registry.

Then my app.config file looks like this:
  <system.diagnostics>
    <
trace autoflush="true" />
    <
sources>
      <
source name="System.Net" tracemode="includehex" maxdatasize="1024" switchName="NetworkSwitch" switchType="MyProject.RegistrySwitch, MyProject">
        <
listeners>
          <
add name="System.Net"/>
        </
listeners>
      </
source>
      <
source name="System.Net.Sockets" switchName="NetworkSwitch"  switchType="MyProject.RegistrySwitch, MyProject">
        <
listeners>
          <
add name="System.Net"/>
        </
listeners>
      </
source>
      <
source name="System.Net.Cache" switchName="NetworkSwitch"  switchType="MyProject.RegistrySwitch, MyProject">
        <
listeners>
          <
add name="System.Net"/>
        </
listeners>
      </
source>
    </
sources>
    <
switches>
      <
add name="NetworkSwitch"  value="Off"/>
    </switches>
    <
sharedListeners>
      <
add name="System.Net" type="MyProject.MyTextWriterTraceListener, MyProject" initializeData="network.log" />
    </
sharedListeners>
  </
system.diagnostics>

Notice that I had to define the CLR type of my switch not in the <Switches> node where the switch is named, but in the switchType parameter on each <Source> that references the switch.  Also note that even though the Value of the switch is set to Off in this configuration file, that value is overwritten when my RegistrySwitch subclass initializes with the value from the registry.

Also note that in this example, my listener is a custom type. It is a TextWriterTraceListener that places the log file in a valid user data path.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>