Developers have been asking for a way to programmatically retrieve information about the call stack at any point from within their code. It would be nice to be able to determine, in code, how you "got" to where you are, or to be able to determine the sequence of procedures that your application "visited" before getting to the current procedure. In specific, developers need to be able to programmatically walk the stack frames, starting with the current procedure, and working back up a specific number of levels, or all the way back to the start of your application.
The .NET Framework provides the functionality as part of the System.Diagnostics.StackFrame class. Along the way, the sample demonstrates two other classes: System.Diagnostics.StackTrace and System.Reflection.MethodInfo. You'll use the StackTrace class created with no parameters sent to its constructor, providing a complete set of StackFrame objects, giving information from the time your application started. You can also use the StackTrace class created by passing an Exception object to its constructor, providing stack trace information back to the code that triggered the exception.
This sample demonstrates two uses of the StackTrace and StackFrame classes: it shows how you can walk all the way back up the stack (all the way back up, as you'll see) at any point, and it shows how to walk the stack after an exception.
On the sample form, click "Test Procedure Stack" to call a procedure several levels deep (the click event handler calls ProcA, which calls ProcB, which displays the call stack). Click "Test Exception Handling" to walk the stack trace associated with an exception.
Requires the Trial or Release version of Visual Studio .NET Professional (or greater).
Clicking the "Test Procedure Stack" button calls ProcA, which calls ProcB. ProcB calls the GetFullStackFrameInfo procedure, passing in a new StackTrace object:
GetFullStackFrameInfo(New StackTrace())
In the GetFullStackFrameInfo procedure, code uses the FrameCount property of the StackTrace object to retrieve the total number of stackframes, working backwards from the current procedure:
Dim fc As Integer = st.FrameCount
The procedure then adds information about each stack frame to the list box on the sample, calling the GetFrame method to retrieve an indexed stack frame object:
For i = 0 To fc - 1
lstStackItems.Items.Add( _
GetStackFrameInfo(st.GetFrame(i)))
Next i
The GetStackFrameInfo procedure calls the GetMethod method of the StackFrame object the code sent it, and then retrieves properties of the MethodInfo object to display information about the procedure in the list box (see the procedure for the details of retrieving method information):
Dim mi As MethodInfo
Dim strOut As String
mi = CType(sf.GetMethod(), MethodInfo)
The "Test Exception Handling" button takes similar actions, but the code triggers an exception and passes that exception to the constructor for the StackTrace object:
Try
ProcException1(1, 2)
Catch exp As Exception
GetFullStackFrameInfo(New StackTrace(exp))
End Try
Passing an exception into the constructor yields a different set of results, as you can see by running the sample. If you investigate the documentation, you'll see that there are other ways to create a StackTrace object. You can, for example, request debugging information such as line numbers. (Note that this feature isn't implemented in the first release of the .NET Framework. It may work in the current release.) Take the time to investigate the documentation on these three objects: StackTrace, StackFrame, and MethodInfo. You'll find a wealth of information about the history behind your procedures, all available to you at runtime.