Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

Archive for Debugging

October 30, 2010

Setting Break Points in the Call Stack Window

Filed under: C#,Debugging,VB.NET,Visual Studio @ 10:37 am

As you are debugging your application, you may want to set a break point further down the call stack. One way to do this is to double-click on the row in the Call Stack to navigate to the code, and then insert a breakpoint. But there is an easier way.

NOTE: For an introduction to using the Call Stack Window, see this post.

For example, in this sample application, the CustomerWin form calls a BindData method which calls a Retrieve method in the business layer which calls an ExecuteDataTable method in the data layer to retrieve the data. Here is the Call Stack window:

image

To assist with debugging, I want to set a break point when the call stack returns to BindData. Here are the steps:

1) Right-Click on the row that shows the call to BindData().

2) Select Breakpoint | Insert Breakpoint.

The Call Stack window then looks like this:

image

Pressing F5 to continue from the current breakpoint, the code will continue until it hits the BindData method.

Use this technique any time you want to set a breakpoint further up the call stack.

Enjoy!

Using the Call Stack Window

Filed under: C#,Debugging,VB.NET,Visual Studio @ 10:23 am

The complexities of today’s software are better managed used techniques such as layered architectures, object-oriented programming, separation of concerns, MVC, and MVVM to name a few. All of these techniques require that your application be separated into logical units, which means that to perform any task, your code needs to call other pieces of code.

For example, in the "old days" your application may have had all of the code that retrieved data and bound it to a grid in one OK Click event handler. Now, the OK Click event handler in the presentation layer may call a command handler in a view which calls a method in a business object of your business layer which calls a method to actually retrieve the data from your data access layer.

The Call Stack Window helps you see these paths through your code and allows you to quickly navigate between them. To see the Call Stack window, put a break point somewhere in your code. Run the application. When the application hits the break point, use Debug | Windows | Call Stack to view the Call Stack window:

image

This figure shows the Call Stack for some C# code, but this window works equally well with VB.NET.

The top row of the Call Stack window grid shows the current location in the code. The row below shows the code that called that method. The row below that shows the line of code that called the prior method and so on.

So reading this from the bottom up:

  • The application started with the Main method in the Program class.
  • The Main method started the CustomerWin form in the CustomerWin class.
  • The startup code in the CustomerWin form called the BindData method in the CutomerWin class.
  • The BindData method called the Retrieve method in the Customers class.
  • The Retrieve method called the ExecuteDataTable method in the Dac class.
  • The ExecuteDataTable method called another overload of the ExecuteDataTable class and hit a break point.

If you want to see the code at any of these points, just double-click on the row in the Call Stack window. Visual Studio will jump to that location in your code. The "current" location is shown in yellow and the calling locations are shown in green.

For example, double-clicking on the Customers.Retrieve row jumps to this code:

image

For more information on using the Call Stack window, see the following:

Use this technique during your debugging process to navigate the call paths in your application.

Enjoy!

April 29, 2010

ToString and the Visual Studio Debugger

Filed under: C#,Debugging,VB.NET @ 5:50 pm

It is always useful to override the ToString method on each your classes. This is especially true when using the Visual Studio debugger.

This example uses the list created in this prior post.

The list is returned from a function and the breakpoint is set immediately after  the return statement. Here is what the data tip looks like when hovering over the custList variable.

In C#:

image

In VB:

image

Notice how the items in the list show their index (0 through 3) in square braces and their class name in the curly braces. You can use the + to access the TreeView and see the property details for the class. But if you have lots of properties, you could be scrolling around to find the key bits of information you need.

You can change the information in the curly braces to contain more useful information by simply overriding the ToString method.

In C#:

public override string ToString()
{
    return this.CustomerId + " (" + this.LastName + ")";
}

In VB:

Public Overrides Function ToString() As String
    Return Me.CustomerId & " (" & Me.LastName + ")"
End Function

In this example, the most important pieces of information about the customer are the Id and last name. So that is what is returned from the ToString method. In your classes, you can return whatever information is useful for your debugging.

Now, when using the same debugging techniques described above, you can see the following when hovering over the custList variable:

In C#:

image

NOTE: For C#, this feature is available in VS 2008 and VS 2010.

In VB:

image

NOTE: For VB, this feature is new in VS 2010.

Now your most useful properties are displayed directly in the data tip. No need to navigate the property tree.

Override the ToString method on every business object to take advantage of this very useful debugging feature.

Enjoy!

September 2, 2009

Global Exception Handler (WinForms)

Filed under: C#,Debugging,VB.NET @ 2:52 pm

Application failures will occur. The user could perform a sequence of
operations or enter a value that you don’t expect, the connectivity to your
database could be interrupted, the code could have a logic error, or many
other possibilities. The .NET Framework provides structure exception
handling (SEH) to help you manage application failures.

An exception is a failure that occurs in your application. Exceptions
fall into two broad categories: expected and unexpected.

Expected exceptions are those that your application plans for and
responds to. For example, you expect that a user-requested customer may
not be found in the database. So you add code to check for this condition
and respond with an appropriate message to the user.

Unexpected exceptions are those that you know may happen, but
don’t necessarily know when or where. These are more difficult to plan for.
Logic errors are a good example of this type of exception. This is especially
true in cases where the logic error corrupts some underlying data and the
exception occurs later when that data is processed, possibly far from the
actual logic error.

Structured exception handling allows you to define a code structure
to handle both expected and unexpected exceptions generated in your application. This is the purpose of the Try/Catch blocks provided in the .NET
Framework.

The goal of exception handling is to never allow the application to abort
with a system error. Your application should handle all expected and unexpected exceptions.

In the case of unexpected exceptions, handle the exception by logging exception details to a file or some other source so that you can more quickly determine the cause of the exception. Then you can display a user-friendly message to the user and terminate the application gracefully.

To catch every possible exception in a Windows Forms application, you need to do one of the following:

  • Ensure that every application entry point has a Try/Catch block to
    catch every possible exception.
    This is actually much harder than it sounds. Since your application
    is event-driven, every event is a possible entry point into your application code. So you would have to add a Try/Catch block to every
    event handler in your application.
  • Write code in the appropriate unhandled exception event.

This post focuses on the second option: writing code in an appropriate unhandled exception event. Implement a global exception handler in a Windows Forms application as follows.

In C#:

In C#, you can trap the ThreadException event.
  1. Select a Windows Application project in Solution Explorer.
     
  2. Open the generated Program.cs file by double-clicking on it.
     
  3. Add the following line of code to the top of the code file:

    using System.Threading;
     
  4. In the Main() method, add the following as the first line of the method:

    Application.ThreadException +=
        new ThreadExceptionEventHandler(Application_ThreadException);

     
  5. Add the following below the Main() method:

    static void Application_ThreadException(
            object sender, ThreadExceptionEventArgs e)
    {
        // Do logging or whatever here
  6.     Application.Exit();
    }

  7. Add code to handle the unhandled exception within the event
    handler.
    Any exception that is not handled anywhere else in the application is
    handled by the above code. Most commonly, this code should log the error and display a message to the user.

NOTE: This code does not really "handle" the error. It just provides a place to log the error, perform any clean up operations, and display a message to the user. Unless you exit the application as shown in the sample code above, the code will attempt to continue, but will most likely be in an invalid state.

NOTE: This code only handles unhandled exceptions from the main UI thread. If you create other threads, they will need their own exception handling.

In VB:

With VB, Windows applications provide application events. One of these application events is the UnhandledException event, which the application generates whenever an unhandled exception occurs. You can write code for this event to catch any exception not specifically handled by your application.
  1. Select a Windows Application project in Solution Explorer.
     
  2. Open the Project Designer for the project by right-clicking the
    project and selecting Properties from the context menu, OR select
    Project | Properties from the main menu bar, OR double-click on
    the My Project folder under the project.
     
    image
     
  3. Select the Application tab of the Project Designer if it is not
    already selected.
     
  4. Ensure that the Enable application framework checkbox is
    checked.
     
  5. Click the View Application Events button.
    An ApplicationEvents.vb code file is added to your project, if it does
    not already exist, and is opened. The generated code is as follows:
  6. Namespace My

        ‘ The following events are available for MyApplication:
        ‘
        ‘ Startup: Raised when the application starts, before the startup form is created.
        ‘ Shutdown: Raised after all application forms are closed.  This event is not raised if the application terminates abnormally.
        ‘ UnhandledException: Raised if the application encounters an unhandled exception.
        ‘ StartupNextInstance: Raised when launching a single-instance application and the application is already active.
        ‘ NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
        Partial Friend Class MyApplication

        End Class

    End Namespace

  7. Select (My Application Events) from the Class Name dropdown
    at the top left of the Code Editor.
     
  8. Select UnhandledException from the Event drop-down at the
    top right of the Code Editor. The following event handler code lines are generated:
     
    Private Sub MyApplication_UnhandledException( _
                         ByVal sender As Object, ByVal e As _
    Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) _
                          Handles Me.UnhandledException
  9. End Sub

  10. Add code to handle the unhandled exception within the event
    handler.
    Any exception that is not handled anywhere else in the application is
    handled by this code. Most commonly, this code should log the error and
    display a message to the user.

NOTE: The VB UnhandledException event never occurs when you are running
with the debugger. When you are running with the debugger, Visual Studio catches the error and assists you with debugging it. To test the code in this event, use the option to "Start Without Debugging".

By setting up a global exception handler, you can ensure that your application catches any unexpected exception and never displays an unfriendly message to your users.

(Based on an except from "Doing Objects in Visual Basic 2005".)

Enjoy!

July 28, 2009

Caller Id: Using StackTrace

Filed under: C#,Debugging,VB.NET @ 12:43 pm

There are situations where you may want to know who called a particular method in your application. Maybe you want to log it or use the information for debugging purposes. Whatever the reason, you can get information on the call stack using the StackTrace class.

A stack trace is basically information on the active stack while a program is running. See this for more basic information on stack trace.

The .NET StackTrace class is detailed here. This post provides some examples of using the StackTrace class to obtain information about the call stack.

If you want to view the entire StackTrace, you can loop through each stack frame.

NOTE: Be sure to set a reference to System.Diagnostics.

In C#:

private string MyMethod(string s1)
{

  StackTrace st = new StackTrace();
  foreach (StackFrame sf in st.GetFrames())
  {
    Debug.WriteLine("Calling class name: " +
                                sf.GetMethod().ReflectedType.Name);
    Debug.WriteLine("Calling method name: " + sf.GetMethod().Name);
    Debug.WriteLine("Full method signature: " +
                                        sf.GetMethod().ToString());

  } 
  return String.Empty;
}

In VB:

Public Function MyMethod(ByVal s1 As String) As String
  Dim st As New StackTrace
  For Each sf As StackFrame In st.GetFrames
    Debug.WriteLine("Calling class name: " & _
                                sf.GetMethod.ReflectedType.Name)
    Debug.WriteLine("Calling method name: " & sf.GetMethod.Name)
    Debug.WriteLine("Full method signature: " & sf.GetMethod.ToString)
  Next
  Return String.Empty
End Function

The GetMethod function gets the method executing in the defined stack frame. The 0th stack frame is the currently executing method. The 1st stack frame is the method that called it, the 2nd stack frame is the method that called that method, and so on up the call stack.

The Name property defines the name of the method. The ReflectedType property defines the class of the calling method and the ReflectedType.Name property provides the name of that class.

The ToString method provides the full method signature. Regardless of the language you are using, the signature will always be displayed in C# style syntax.

For example, the first few stack frames from my example application are as follows:

Calling class name: TestWin
Calling method name: MyMethod
Full method signature: System.String MyMethod(System.String)

Calling class name: TestWin
Calling method name: WorkWithMethods
Full method signature: Void WorkWithMethods()

Calling class name: TestWin
Calling method name: TestWin_Load
Full method signature: Void TestWin_Load(System.Object, System.EventArgs)

If you only want information about the direct caller, you can access the first stack frame.

In C#:

StackTrace st = new StackTrace();
StackFrame sfFirst = st.GetFrame(1);
Debug.WriteLine("Calling class name: " +
                            sfFirst.GetMethod().ReflectedType.Name);
Debug.WriteLine("Calling method name: " + sfFirst.GetMethod().Name);

In VB:

Dim st As New StackTrace
Dim sfFirst As StackFrame = st.GetFrame(1)
Debug.WriteLine("Calling class name: " & _
                            sfFirst.GetMethod.ReflectedType.Name)
Debug.WriteLine("Calling method name: " & sfFirst.GetMethod.Name)

This code provides the name of the class and method that directly called the current method:

Calling class name: TestWin
Calling method name: WorkWithMethods

Enjoy!

July 14, 2009

Debugging: Heisenbug

Filed under: C#,Debugging,VB.NET @ 5:32 pm

Being a physics major in college, I am familiar with the Heisenberg Uncertainty Principle which basically states that in quantum physics, some properties (like position and momentum) cannot both be known to any precision.

Though not technically accurate, the Heisenberg Uncertainty Principle is often simplified to what is called the observer effect. This refers to the fact that the act of observing something can change its behavior.

This is very often true in programming, especially when it comes to debugging. The act of debugging an application can alter how the application behaves. Due to the comingling of the meaning of the Heisenberg Uncertainty Principle and the observer effect, the types of bugs that disappear or are altered by observing them are sometimes called heisenbugs.

Ever try debugging drag and drop operations? How about mouse movements?

Have you found any heisenbugs in your code? Want to share them? Post your thoughts using the comments.

Thanks!

July 10, 2009

DAL: DataTable Visualizer

Filed under: C#,Data,Debugging,VB.NET @ 3:05 pm

This post details how to use the DataTable Visualizer. The DataTable Visualizer is a debugging tool that allows you to see and edit the contents of a DataTable while you are debugging.

NOTE: There is also a DataSet Visualizer that works the same way for DataSets instead of DataTables.

To use the DataTable Visualizer:

  1. Set a break point on any line of code after you have a DataTable populated.
     
  2. Run your application until it stops at the break point.
     
  3. Hover over your DataTable variable.
    You should get a tooltip that displays a magnifying glass. image
    Note: Though this example shows C# code, this technique works the same in VB.
     
  4. Click on the arrow next to the magnifying glass to display the drop down menu.
    image
  5. Select the "DataTable Visualizer" menu option.
    The DataTable contents is then displayed:
    image

This allows you to view your DataTable and optionally update the data in the table for debugging or testing.

Enjoy!

© 2014 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs