Saturday, September 12, 2015

[ C# ] - Using Debugger Break, Log and getting Stack Trace

1. Introduction

The "Debugger Class" is availble under System.Diagnostics name space which will help us in easy diagnostics of the application. In this article we will examine the usage of the debugger class and using that we will see breaking through the code, logging and dynamically taking the snap-shot of the call stack.

2. About the example

The screenshot of the sample application is shown below:

C# Print StackTrace Example - Screenshot

The textbox marked as 1, shows the status of the debugger. When the application is attached with the debugger, the status shows attached. Clicking the refresh button (Marked as 2) updates the debugger status. Clicking the Break On Code button (Marked as 3) dynamically breaks the application as breakpoint is hit. This is useful when you want to break the application without the breakpoint. Clicking the Debug Log (marked as 4) button produces the log entries in the debug output window. In the same debug output window, the application call stack is printed whenever the Output Stack Trace button (Marked as 5) is clicked.

The sample application uses functionalities provided System.Diagnostics namespace.

3. Checking the debugger status

The status of the debugger can be checked using the "IsAttached Property" of the "Debugger Class". When the application is attached to the debugger, this property is set to true. By making use of this below specified function is written:

//Sample 02: Set state of the debugger
public void SetDebuggerState()
{
    if (Debugger.IsAttached == true)
        txtDebuggerState.Text = "Attached";
    else
        txtDebuggerState.Text = "Not Attached";
}

This function is called in the form load as well as Refresh button click handler. The function after checking the debugger state indicates status of the debugger in the “debugger state” textbox. Below is the code which makes use the SetDebuggerState function:

private void frmDebugAttr_Load(object sender, EventArgs e)
{
    //Sample 03a:Check the State of the Debugger
    SetDebuggerState();
}

private void cmdRefresh_Click(object sender, EventArgs e)
{
    //Sample 03b:Check the State of the Debugger
    SetDebuggerState();
}


Below is the video which checks the status with and without the debugger.

Video 1: Checking the Debugger State




4. Dynamically Breaking on the Code

The "break() Method" of the debugger class is used to break the application dynamically. At runtime when the function break is called, the code breaks at the call to the break. This happens when the debugger is already attached. Otherwise, a window appears stating; user break point encountered and asks you to select the debugger among the list available debugger in the machine. Below is code which breaks the application dynamically:

private void btnBreakOnCode_Click(object sender, EventArgs e)
{
    //Sample 04: Break on the Code
    if (Debugger.IsAttached == true)
        Debugger.Break();
    int x = 15;
    int y = x + 5;
}

In the above code, the Break is called only when the debugger is attached to the application. Have a look at the below video to see how we break into the code without the break point:

Video 2: Breaking into code dynamically




5. Log Debug information on Output Window

The "Log() function" of the "debugger class" is used to log the debugging information on the output window. This method does not perform any action when debugger is not attached to the application. Have a look at the below piece of code:

private void btnDebugLog_Click(object sender, EventArgs e)
{
    int x = 15;
    //Sample 05: Log informations
    if (Debugger.IsAttached == true)
    {
        Debugger.Break();
        string LogString = String.Format("Value in x = {0}", x);
        string newline = System.Environment.NewLine;
        Debugger.Log(0, "Information", "Debugger Attached" + newline);
        Debugger.Log(0, "Information", LogString + newline);

    }
}

Here, we are first checking the debugger is attached or not. When debugger is in attached state, we dynamically breaking the code by calling "Debugger.Break()". After that two we are forming the Log information to examine the content of the variable x. Finally the call to "Debugger.Log()", flushes the log information to the output window of the debugger. The below video shows the Log information on the output window:

Video 3: Logging Custom Information



6. Logging Function call stack to Output Window  


Sometimes we may need to log the function call stack in a log file. The call stack information is useful when it is logged in the exception handlers. The "StackTrace Class" will give us the snapshot of the function call order. Once the snapshot is available, other call related information can be retrieved from "StackFrame". The code for the “Output Stack Trace” button click handler is given below:

//Sample 06: Getting Stack Trace Information
private void btnStackTrace_Click(object sender, EventArgs e)
{
    DispoutCallStack();
}

It is obvious that we are making call to a function DispoutCallStack(). Inside this function, the function call stack information is logged into the output window. Code for this function is given below:

//Sample 06: Getting Stack Trace Information
public void DispoutCallStack()
{
    //Sample 6.1: Get Total number of functions
    StackTrace trace = new StackTrace(true);
    int total = trace.FrameCount;

    for (int Frame_index = 0; Frame_index < total; Frame_index++)
    {
        //Sample 6.2: Iterate through each stack frame and display the info
        StackFrame frame = trace.GetFrame(Frame_index);
        String StackLine = String.Format("[{0}], Func:" +
        "{1}, FileName: {2}[{3}]", Frame_index,
        frame.GetMethod(),
        frame.GetFileName(),
        frame.GetFileLineNumber());

        //Sample 6.3: Display Stack Trace Information on output Window
        Debugger.Log(0, "Information", StackLine);
        Debugger.Log(0, "Information", Environment.NewLine);
    }
}

In the function, the trace instance of type StackTrace is created and here we get the entire stack frame in a collection. Next in a for loop we retrieve the Stack Frames one by one and in each iteration, the retrieved StackFrame information is used to collect the other call related information. The collected information is stored in a string variable StackLine and then this stack line is displayed in the output window using the technique that we saw in the previous section. Have a look at the below video to see how the Function call stack information is displayed in the output window:

Video 4: Logging Function Call Stack

Source Code: Download

No comments:

Post a Comment

Leave your comment(s) here.

Like this site? Tell it to your Firend :)