1. Tracing Need
In this example, we will learn how to push C# debugging message into the Trace File and Windows Event Logger. This is useful when we deploy the application in the customer place. Debugging an application in customer site is almost not possible as we do not keep the source code in there. When we proceed with the example, we will learn Trace Source, Trace Switch and Trace Listeners.
The screen-shot below shows our Example and you can download it from the link at the bottom of this article. Here, we will not explore how the application performs prime number summation. But, will learn how to perform tracing using the C# API.

C# Application Tracing Example
2. Tracing Components – Source, Switch & Listener
To understand this easily have a look at the below diagram:

Dotnet Debug Tracing Components
The Trace Source forms the application specific debug messages & sends that to the external world. In general, it is your application which sends the trace messages for review purpose. The
TraceSource
Class of the ‘Dotnet Framework’ contains useful member functions to push the trace messages from the application.
Trace Listeners are recording media, which receives information from Trace Source and stores it. The listener can be a flat text file, a XML file, Console output window or a Windows Event Logger and even more exists. These listeners are attached to the Trace source so that send and receive becomes easy.
Note:
A Trace Source can have multiple listeners.
Trace Switch is the intermediate common filter between all the listeners hooked up to a specific Trace source. Hence, trace switch can do the first level of filtering which impacts all the listeners. A trace source can send a variety of trace data classified as Information Messages, Critical Messages, Error Message etc., So here we can set the switch to drain a specific message types. For Example, we can set the switch so that all the trace type except Critical messages gets filtered. As a result, only Critical Messages moves out to the listeners.
There is one more filtering available in the listener itself. In our demo, we will use the filter in the trace switch level to reduce the length of this article. But, I will show how one can put second level filter. This filter is specific for the individual listeners and we can call it as 2nd level filters.
3. About The Downloadable Sample Application
The sample application has two radio buttons and two check boxes. In the above screenshot, it looks like a toggle button. To set the needed properties for the controls download the example and set those which shows in BOLD. The radio buttons tells the example what messages needs to be filtered. The toggle buttons turns ON/OFF the listeners. In our example, the trace stops are text files and Windows Event Log.
OK. Let us explore the code that enables the tracing for our sample. If you do not want the explanation, you can go to the attached sample and start exploring the code.
Search Tag: //Trace 0
4. Default Trace Listener
The Default Trace Listener is the debugger output window. In this section, we will send the trace messages to the output window of the debugger. Then in the coming sections, we will move to Text Listener and Event Logger Listener.
4.1 Declarations
First, we provide the required name space to use the Tracing API. Below is the code snippet:
1 2 |
//Trace 007: Include diagnosis Namespace using System.Diagnostics; |
Next, we introduce member variables for Source and Switch in the Form Class. Below is the code:
1 2 3 4 |
//Trace 008 : Declare the Trace Source, //Trace Switch TraceSource TrcSource; SourceSwitch TrcSwitch; |
4.2 First Level Message Filter at Trace Switch
Now we create the Trace Source and Trace Switch objects in the constructor of the windows form. The
Level
property of the
SourceSwitch
tells what needs to be filtered at Source Level. We set the Level property to All by using the
SourceLevels
enumeration constant. Then, we attach the Trace Switch and the Trace Source. That’s all. What have we done? As already stated, the default listener is debugger output window. Since we set Level property as all, no first level filtering occurs at the Trace Switch. All the trace log messages escape the switch and reach the debug output window. Below is the code:
1 2 3 4 5 6 7 8 9 |
//Trace 009: Create the Trace Source,Switch, TrcSource = new TraceSource("Trace Source"); TrcSwitch = new SourceSwitch("Trace Switch"); //Trace 010: Set the Switch Levels TrcSwitch.Level = SourceLevels.All; //Trace 011: Set the above created switch to Trace Source TrcSource.Switch = TrcSwitch; |
4.3 Send Trace Messages to Debug Output Window
Our tracing is ready and let we pump the debug messages. The
TraceInformation
function of the ‘
TraceSource
’ will pump the Trace Logs to all listener attached to the source. At present, it is only the Debug Output Window as we do not specify any listener explicitly. Our Example sends the Information messages to Output Window when a prime number is detected. Below is the code:
1 2 3 4 5 |
//Trace 012: Write the Trace to the Output Window String info = string.Format( "Prime Number Detected: {0}", i); TrcSource.TraceInformation(info); TrcSource.Flush(); |
Now we can run the sample for testing with 24 as the input number. Right click on the output window and select clear all to wipe out existing texts and then, click Get prime sum button from our example. Look at the output window to see the pumped in trace messages. The screen shot is given below:

Trace Logs Information In Debug Output Window
5 Trace Logs in Text File Using TextWriterTraceListener
In our sample application when the user clicks the toggle button ‘File Log’, we will enable the File Trace Logging and will write our Trace Logs to a text file using ‘
TextWriterTraceListener
’. The text log enabled application is below:

Enabling Text Log Listener
In our example, when the user clicks the same button again, the log will be disabled. So, we will create the Text File Listener and attach it to the Trace source when the check box is in the checked state and remove it when the check box is in the unchecked state.
When the check box is checked, we create a ‘
TextWriterTraceListener
’ object by specifying a name to it. The name is useful when we want to remove it later. We also need to provide File name with path in which the pumped messages flow in. Using the
TraceOutputOptions
Property we can set the time and threads as per the need. One can Refer MSDN for more output options. Once the listener is ready, we attach it to the Trace Source. At this stage, we have two listeners for the Trace Source. So the all the messages coming out of the Trace Switch will now go to ‘C:\Trace.log’ and debugger output window.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private void chkLogFileTrace_Click(object sender, EventArgs e) { if (chkLogFileTrace.CheckState == CheckState.Checked) { //Trace 013: Create text file Listener and //set the output options TextWriterTraceListener txtListen; txtListen = new TextWriterTraceListener( @"C:\Trace.log", "Text Trace Listener"); txtListen.TraceOutputOptions = TraceOptions.Timestamp | TraceOptions.ThreadId; //Trace 014: Add the Listener to the TraceSource TrcSource.Listeners.Add(txtListen); } |
We remove the listener when the check box is in the unchecked state. Note, we referred the Listener name which we gave in the constructor of
TextWriterTraceListener
when we created it. Below is the code:
1 2 3 4 5 |
else { //Trace 015: When the Toggle is off, remove the listener TrcSource.Listeners.Remove("Text Trace Listener"); } |
Run the Sample now to check we are getting the pumped Trace Log in both the listeners when the File Log is toggled on.
6. Trace Logs in Windows Event Logger Using EventLogTraceListener
Event Logger is a windows tool that hides the underlying file and shows the log information in a user interface. However, we can copy the content to a flat file. To view the Event Logger, one should right click on the ‘My Computer’ icon and select ‘Manage’ from the context menu to display the Event Logger. In the left pane he or she should expand the Event Viewer and click on the System node. The right-side pane now shows all the events logged. Double-clicking an Event displays the detailed information about the Event. Below is the screen-shot of the Event Logger:

Windows Event Logger
Now we will make our sample to write the debugging trace content in the ‘Event Logger’. Here, we use C#
EventLogTraceListener
Class to achieve this. The code logic is like the one explained in the previous section. Here, we create
EventLogTraceListener
and rest is same. Below is the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private void chkEventLog_Click(object sender, EventArgs e) { if (chkEventLog.CheckState == CheckState.Checked) { //Trace 016: Create the event log listener and //add it to the Listener collection of //Trace Source. EventLogTraceListener evtListener; evtListener = new EventLogTraceListener( "Event Log Listener"); TrcSource.Listeners.Add(evtListener); } else { //Trace 017: Remove the listener TrcSource.Listeners.Remove("Event Log Listener"); } } |
Now we can test the sample by enabling the Event Log toggle in it. This will use the
EventLogTraceListener
and directs the log message to Windows Event Logger. We should look at the Log Entries in the Application Event Log as it will not enter the system Event Log.
7. Trace Filters Setup
Remember, in the constructor, we asked the Trace Switch to allow all the information flow to the listeners attached to it. Now through Filter Radio Buttons in the example, we will do the filtering of the Trace Log data. The code is straightforward, and it is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private void RadError_CheckedChanged(object sender, EventArgs e) { //Trace 018: Filter the Trace TrcSwitch.Level = SourceLevels.Error; } private void RadInfo_CheckedChanged(object sender, EventArgs e) { //Trace 019: Filter the Trace TrcSwitch.Level = SourceLevels.Information; } |
Below is the screen-shot which was taken from the MSDN. It shows the trace levels and what it filters.

Trace Levels From MSDN
All right. Till now in our code, we wrote only the information messages. How do I check the filters are working fine? Well. Add the below piece of code in the Get Prime sum handler:
1 2 3 4 |
//Trace 016: Log the Trace Errors TrcSource.TraceEvent(TraceEventType.Error, 3, "Invalid Number Specified"); TrcSource.Flush(); |
Note, this time we are not making a call to the Trace Source function
TraceInformation
. We are making a call to the
TraceEvent
function and setting the
TraceEventType
as
Error
. Once again refer the MSDN for other enumeration values. To test the example, provide a number in the input box and click the Get Prime Sum button.
Each individual listeners can also filter the Trace Logs. We can perform message filtering at the listener level and it is called second level filtering. The filters at listener level takes same enumeration values shown above.
Source Code Download Link: C# Log Tracing Example from Google Drive
Categories: C#
Tags: C# EventLogTraceListener, C# TextWriterTraceListener, C# Trace Listener, C# Trace Source, C# Trace Switch