Click here to Skip to main content
13,830,588 members
Click here to Skip to main content
Add your own
alternative version


39 bookmarked
Posted 3 Mar 2005
Licenced CPOL

World's easiest Trace function

, 3 Mar 2005
Rate this:
Please Sign up or sign in to vote.
Add tracing capability to your app with one easy function


Debugging your way through code can be boring and tiring. When you're hunting down a bug, it helps if you can zero right in on the problem. By adding a simple trace file to your app, you can pinpoint the exact sub or function where things went wrong.

With a bit more work, you can configure your app to turn on or turn off writing to the trace file as needed. You can also start with a fresh trace file every time your app is loaded.

With the trace mechanism in place, you can run your app until things go wrong. Then by examining the trace file, you know just where to turn in your code.

This simple approach uses .NET's StackTrace feature to keep track of where users have been as they work with your app.


StackTrace is part of the System.Diagnostics namespace, so you will want to include a reference to that in your project with an Imports statement at the beginning of your class or module.

StackTrace is a pile of StackFrames. Each StackFrame holds information about each function or sub as your application accesses it. Every time a function or sub is accessed, information in the form of a StackFrame about it is pushed onto the top of the StackTrace. This information is available as a string, which we can easily parse to extract just the information we want.

There are two parts to using this mechanism: writing a short subroutine to write material to the trace file, and adding a line to each sub or function calling that subroutine. Let's look at the subroutine first. I've simplified the code somewhat to make it easier to follow, and I use some constants that I've defined elsewhere; their values should be obvious.

Friend Sub Tracer()
       Dim texttoadd As String
       Dim logtext() As String
       Dim fileline() As String
       Dim fs As StreamWriter
       Dim strace As New StackTrace(True)
           If Not File.Exists(TRACE_LOG) Then
               fs = File.CreateText(TRACE_LOG)
               fs.Write("Trace Log " & Format(Now) & CR & CR)
           End If
           logtext = strace.GetFrame(1).ToString.Split(SPACE)
           fileline = logtext(6).Split(BACKSLASH)
           Dim i As Integer = fileline.GetUpperBound(0)
           texttoadd = logtext(0) & COLON & SPACE & _
                fileline(i).Substring(0, fileline(i).Length - 2)
           fs = File.AppendText(TRACE_LOG)
       Catch ex As Exception
       End Try

   End Sub

The StreamWriter is the mechanism used to write the information to the log file. If you are unfamiliar with writing streams, check out the .NET documentation on the topic.

The StackTrace is created using the optional True parameter to indicate that we want the trace to include information about the file the function or subroutine belongs to. The nice thing about the StackTrace is that it holds information about everything that has already happened in the application. In fact, the information we want is not even on the top of the stack--it's one item down, because the last item pushed onto the stack is the call to our Tracer() routine. That's why when we capture the StackFrame we want, we have to get the second item (in a zero-based array).

We can confidently split the StackFrame to an array because these entries always have the same format. The first element in the array will contain the name of the sub or function we want to capture. The last element will have the name of the source file as well as the line number and offset. A typical logtext array will look something like this:

(0): "myFunction"
(1): "at" 
(2): "offset" 
(3): "87" 
(4): "in" 
(5): "file:line:column"
(6): "C:\ProgramFiles\VS\MyProject\MyModule.vb:12345:67

We can then confidently split the last element of logtext into an array, using the backslash as the delimiter. We only care about the last element of that array. Note, though, that the last element actually ends with a line-end character, so we must parse that away before we write to our trace file. (If you don't parse it away, your trace file will end up double-spaced, which you might prefer.)

The second part of the setup is easy: Just add a call to Tracer() in every function or sub you want to include in your trace file:

Private Sub DoSomething(somethingToDo as String)
   somethingToDo = somethingToDo & somethingElse
End Sub

To turn the trace on and off at will, you can add a global Boolean variable to your code, and then examine the state of that variable at run-time to decide if you are tracing or not. The easiest way to do this is to pass a command-line argument:

Class MyMainForm
Public traceIt as Boolean = False

Public Sub Main()
   If Environment.CommandLine.IndexOf("/t")> 0 then traceIt = True

End Sub

Private Sub DoSomething(somethingToDo as String)
   If traceIt Then Tracer()
   somethingToDo = somethingToDo & somethingElse
End Sub

Finally, to start a new trace file every time you start your app, add a line to the main program block to delete the existing file:

If File.Exists(TRACE_LOG) then File.Delete(TRACE_LOG)

You can apply the same technique in a Try/Catch block as well, and incorporate the exception in the trace file. But I'll leave that for you to play with.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer
United States United States
Terpy is a consultant reluctantly based in Olympia, Wash. She'd much rather be back in Maine, where the ocean is on the correct side of the road. She is largely a self-taught programmer who clings jealously to her bad habits. Handbells, anyone?

You may also be interested in...

Comments and Discussions

GeneralGreat Idea [modified] Pin
Eradikator13-Feb-07 22:51
memberEradikator13-Feb-07 22:51 
Questionspace in path Pin
mjstraka19-Aug-06 19:24
membermjstraka19-Aug-06 19:24 
AnswerRe: space in path Pin
terpy19-Aug-06 20:11
memberterpy19-Aug-06 20:11 
GeneralSystem.Diagnostics members Pin
Marcus Poilus31-Mar-06 3:49
memberMarcus Poilus31-Mar-06 3:49 
AnswerRe: System.Diagnostics members Pin
terpy31-Mar-06 6:10
memberterpy31-Mar-06 6:10 
GeneralRe: System.Diagnostics members Pin
Marcus Poilus31-Mar-06 7:16
memberMarcus Poilus31-Mar-06 7:16 
AnswerRe: System.Diagnostics members Pin
terpy31-Mar-06 7:39
memberterpy31-Mar-06 7:39 
GeneralRe: System.Diagnostics members Pin
Marcus Poilus31-Mar-06 8:42
memberMarcus Poilus31-Mar-06 8:42 
GeneralSimple is good Pin
Jason Titcomb16-Apr-05 4:13
memberJason Titcomb16-Apr-05 4:13 
GeneralRelease Mode Pin
Neil Baliga4-Mar-05 7:15
memberNeil Baliga4-Mar-05 7:15 
GeneralRe: Release Mode Pin
terpy7-Mar-05 12:58
memberterpy7-Mar-05 12:58 
Generallog4net Pin
Uwe Keim3-Mar-05 18:08
sitebuilderUwe Keim3-Mar-05 18:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190114.1 | Last Updated 3 Mar 2005
Article Copyright 2005 by terpy
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid