1. Introduction to System.Diagnostics NameSpace
The ‘Debugger Class’ is packed under System.Diagnostics name space which will help us in easy diagnosis of the application. Because this class allows contact with windows debugger the debugging becomes easy. In this article we will delve into the usage of the Debugger Class and using that we will see breaking through the code at runtime & logging messages. The StackTrace class from the System.Diagnostics namespace allows taking the snapshot of the function call stack at runtime.
2. About The Example
The picture here shows the screenshot of the sample application:
The text box marked as 1, shows the status of the debugger. When we attach the application 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 manual insertion of breakpoints. When we click the Debug Log (marked as 4) button, the example produces the log entries in the debug output window. In the same debug output window, we print the application call stack whenever user clicks the Output Stack Trace button (Marked as 5).
The sample application uses functionalities provided System.Diagnostics namespace.
3. Getting Debugger Status
We can check the status of the debugger using the IsAttached Property of the Debugger Class. When the application is attached to the debugger, C# sets this property to true. The below code snippet is making use of this property:
1 2 3 4 5 6 7 8 |
//Sample 02: Set state of the debugger public void SetDebuggerState() { if (Debugger.IsAttached == true) txtDebuggerState.Text = "Attached"; else txtDebuggerState.Text = "Not Attached"; } |
We call the above function from the form load and Refresh button click handler. The function after checking the debugger state shows the status of the debugger in the Debugger State textbox. Below is the code which makes use of the SetDebuggerState function written by us:
1 2 3 4 5 6 7 8 9 10 11 |
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 attaching the debugger with our source code:
Video 1: Checking the Debugger State
4. Break Into Debugger for Debugging
The Break() Method of the Debugger Class is used to break the application dynamically. At runtime when we call the function Break, the code stops the execution at the call to the Break(). This happens when the debugger is already linked. Otherwise, a window pops up stating; user break point found and asks you to select the debugger among the list of possible debuggers in the machine. Below is the code which breaks our example dynamically:
1 2 3 4 5 6 7 8 |
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, we use the IsAttached property. We call the Break() function only when the debugger is attached to the running 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 for Debugging
5. Logging Debugging Message into Console 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 we do not attach debugger to the application. Have a look at the below piece of code:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 status of the debugger with the source code . When debugger is in attached state, we dynamically breaking the code by calling Debugger.Break(). After that we are forming the Log message to review the content of the variable x. Finally, we call to Debugger.Log(). This call will flush the log message to the output window of the debugger. The below video shows the Log information on the output window:
Video 3: Logging Custom Debugging Information
6. Logging Function Call-Stack
Sometimes we may need to log the function call stack in a log file. The call stack information is useful when the code throws exception or fault condition. The StackTrace Class will give us the snapshot of the function call order. Once the snapshot is available, we can retrieve other call related information from Stack-Frame. The code for the Output Stack Trace button click handler is below:
1 2 3 4 5 |
//Sample 06: Getting Stack Trace Information private void btnStackTrace_Click(object sender, EventArgs e) { DispoutCallStack(); } |
We are making a call to a function DispoutCallStack(). In this custom function, we are logging the function call stack information into the output window. Code for this custom function is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//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. In each iteration, we retrieved StackFrame information to collect the other call related information. Next, we form the collected information in a string variable StackLine and then we display it in the output window using the technique which we saw in the previous section. Have a look at the below video to see how we display the Function call stack information in the output window:
Video 4: Logging Function Class Stack Frame Information
Source Code: Download System.Diagnostics Objects Example From Google Drive
Categories: C#
Tags: Debugger.Break, Debugger.IsAttached, Debugger.Log, StackTrace::GetFileName, StackTrace::GetLineNumber, StackTrace::GetMethod