LANGUAGES: VB .NET
TECHNOLOGIES: Stack Trace | Exceptions
Generate a Stack Trace Anytime, Anywhere
Validate a program's logic, record information about different states of the application, and take the pulse of what's happening in your app.
By Don Kiely
In a recent article (Probe the Secrets of the Stack Trace), I talked about using the stack trace - that cryptic list of object names, line numbers, and gobbledy-gook that seems like too much work to analyze and grok to solve debugging problems. Hopefully I convinced you that there are valuable nuggets of information there, at least for problems that aren't solved quickly by examining the offending line of code or its neighbors.
A stack trace is a useful tool, and not only when an exception arises. You can use it to validate a program's logic, record information about different states of the application, and take the pulse of what's happening in the app. If you're stepping through your code, you can use the Call Stack window (see Figure 1) to see exactly where you are in program execution.
Figure 1. Double-click on any entry in the Call Stack window to go directly to the code.
Like most things in the .NET Framework, Microsoft made the call stack available as a class you can use anytime to get a snapshot of where you are in an application. It's named the StackTrace class, and you'll find it in the System.Diagnostic namespace. This class has three interface features of interest in custom code:
- The FrameCount property: A stack frame is one entry in the trace, containing all the relevant information about that code location. This property, of course, returns the number of frames currently in the stack.
- The GetFrame method: Takes an integer and returns the specified stack frame. These are numbered from zero, which is the last frame pushed onto the stack, to the current code position.
- The ToString method: This is overridden to generate a readable representation of the stack trace, which is what you see in the default exception page generated by ASP.NET.
One thing you should be aware of is the stack trace changes with each line of code you execute. So the StackTrace class takes a snapshot of the trace when you create the object, letting you read its contents without changing dynamically.
The StackFrame class gives basic information about the frame, including source-code filenames and locations if the app was compiled with debug symbols. What really makes it powerful is if you use .NET Reflection to get additional information about the type. This is particularly useful for frames that represent a framework method rather than your custom methods.
Using these classes is fairly straightforward. Figure 2 shows the results of running a sample application to build a table with information about the stack trace, as well as the readable default trace that .NET generates (keep in mind that I'm a coder and my graphics design gene was removed at birth).
Figure 2. This table results from running the sample application (available for download) with information about the stack trace.
Start by instantiating a new instance of the StackTrace class. It has several constructors to customize exactly what is saved in the snapshot. Here I'm using a version that includes all available stack frames and capturing source code information if available (in the code that follows, I'm omitting the lines that create new table rows and cells):
Dim sTrace As New StackTrace(True)
Then the code loops through the collection of frames and reading properties:
While iCount < sTrace.FrameCount
Dim frame = sTrace.GetFrame(iCount)
tblCol.Text = frame.GetFileName
tblCol.Text = frame.GetMethod.Name
tblCol.Text = frame.GetFileColumnNumber
tblCol.Text = frame.GetFileLineNumber
tblCol.Text = frame.GetMethod.ToString
iCount += 1
Two of the interesting lines use the GetMethod method of the StackFrame class. This technique returns the method in which the frame is executing, returning a MethodBase object, which is part of the System.Reflection namespace. Using this object, you have access to all the metadata about both your custom code and the .NET Framework code - a deep pool of interesting information.
Using code like this you can explore the depths of .NET code and build your own exploration tools. And you'll get to the heart of any problems your code is having.
The sample code in this article is available for download.
Don Kiely is senior technology consultant for Information Insights, a business and technology consultancy in Fairbanks, Alaska. E-mail him at mailto:[email protected].