I must say that I ignored Trace object and TRACE compilation constant for long time. I've been only using Debug object and DEBUG constant for debugging purposes.
Recently, one user of our VSdocman encountered strange problem which I couldn't reproduce. We all know it. So I created special tracing build for him which logged all important activity, variable values and obviously exceptions. The problem was isolated and fixed in one day.
So, how can Visual Studio and .NET framework help us with the tracing? We can use built-in Trace class. This class works similarly to Debug class. It is only compiled into your assembly if TRACE constant is True. VS automatically sets TRACE constant to True for both Debug and Release configurations. You can change this constant in your project properties. Go to Configuration Properties, Build and check or uncheck Define TRACE constant. I have disabled this in "Release" configuration and created a copy of "Release" configuration (see here for more info) named "Release with Trace" where I enabled TRACE.
Now I only put Trace.WriteLine in the code. You can also use more complex methods of Trace class, define conditions, error levels etc. I won't describe them here.
But wait, is that all? Not at all. There are several issues related to tracing.
-
You might thing that all code containing Trace won't be compiled if TRACE constant is false. This is not true. If you look at Trace members documentation, you will notice that only Trace methods have set <Conditional("TRACE")> attribute. ConditionalAttribute class is very interesting attribute which causes that calls to methods with this attribute are ignored and not compiled. But Trace properties don't have <Conditional("TRACE")> specified so they are always compiled. For example Trace.Listeners is always compiled and you may fall in troubles if you don't keep it in mind. If you don't want to compile this code if TRACE=False, then use standard conditional compilation statement:
#If Trace Then ... #End If
-
Write variables with Nothing (null) value correctly. Nothing value is very common reason why your program doesn't work as expected. I'm using the following function:
#If Trace Then '''<summary> ''' The same as Object.toString but handles Nothing correctly. '''</summary> Friend Function toStr(ByVal obj As Object) As String Try If obj Is Nothing Then Return "Nothing" Else Return obj.ToString End If Catch ex As Exception Return "Nothing" End Try End Function #End If
-
You probably want your tracing information be written in file so the end-user can send it to you. You need to add your own listener to Trace class. The following code writes the log information into USER_APP_DATA\VSdocman\trace_log.txt file. You need to place it in your code before any other Trace method is used.
#If Trace Then Try Dim myTextListener As TextWriterTraceListener Dim userAppData As String userAppData = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) ' Create a file for output named trace_log.txt in Application data folder. IO.Directory.CreateDirectory(IO.Path.Combine(userAppData, "VSdocman")) Dim myFile As IO.Stream = IO.File.Open(IO.Path.Combine(userAppData, "VSdocman\trace_log.txt"), _ IO.FileMode.Create, IO.FileAccess.ReadWrite, IO.FileShare.Read) ' Create a new text writer using the output stream, and add it to ' the trace listeners. myTextListener = New TextWriterTraceListener(myFile) Try If TypeName(myTextListener.Writer).Equals("StreamWriter") Then CType(myTextListener.Writer, IO.StreamWriter).AutoFlush = True End If Catch e As Exception End Try Trace.AutoFlush = True Trace.Listeners.Clear() Trace.Listeners.Add(myTextListener) Catch ex As Exception End Try #End If