You are on page 1of 78

Stack Windows Breakpoint

Lession 1 – Using the Call Stack Window and Breakpoints

This is the project that we need to learn debugging with.

Many different types of applications can be debugged with the techniques we discuss
here:

WPF

ASP.NET

Silverlight

WCF

WinForms
MVC

Mobile Development

Workflow

C++

Language Agnostic

C#, Visual Basic, Debugger Is Language Agnostic

Advanced Breakpoints

Stop in break mode only when you want to

Customize actions when you hit breakpoint

We want to know why and where to use adv breakpoints

Solve in a day versus several weeks

You should start on paper

Develop a strategy before blindly going debugging

You need both the Visual Studio projects and the PDB files

These allow you to work with advanced features

Assemblies in address space are referenced by pdb files

Setting a breakpoint
Now start debugging.
Notice the call stack is displayed. And as we would expect, we can see that we are resting
at the breakpoint in a deeply nested call stack.
You can see that our breakpoint is at Doh(). Notice the the buttonDeepStack_Click called
“Do()” and that “Do()” called “Re()” and so on.

But what if we wanted to break at the top of the stack - buttonDeepStack_Click()?

The answer is to set a breakpoint within the “Call Stack” window. We can use the “Call
Stack” window to set breakpoints.
You can see that we stopped at “buttonDeepStack_Click”. This approach makes it
convenient for to break anywhere in the call stack depending on the needs of your
debugging experience.

Lession 2 – SubExpression Breakpoints

It is possible to set breakpoionts in any of the 3 sections of the for loop below. As you know
section “1” executes once at the beginning of the loop. Section “2” (the condition) executes
once at the top of each for loop. Finally, section “3” executes once at the end of each loop.
So put your cursor any of the 3 sections and hit the “F9” key, the “Insert Breakpoint” command.

To clear the subexpression breakpoints

Using the BreakPoint Dialog Box – Just type in a name into the “New Breakpoint” Dialog Box
The beauty of it is that you can leverage the intellisense feature. Choose “Debug | New
Breakpoint | Break at Function.”

Be sure to have the “Use IntelliSense to verify the function name” selected. Notice in the
example below that Visual Studio is complaining that we mis-spelled Callevenmore. The
intellisense is protecting us.

If we spell things correctly, our breakpoint works.


If you have the same method in multiple classes, you can dis-ambiguate by preceding the
method name with the class name as follows:

Note that the “MainForm” class name precedes “CallEvenMore.”

But what if you have a function that is overloaded or in multiple classes?

Simple. Just type in that function name and a list will appear.
Notice that we can choose the one we wish to set a “BreakPoint” at. You could have narrowed
the list by writing “Overload(int).”

Lession 3 – Breakpoint Hit Count

This setting determines how the breakpoint should behave when it is hit. You can choose to:

Break always, regardless of hit count. This is the default option. This option has the least
effect on program performance, since the debugger does not actually bother to compare the
values.

Break when the hit count is equal to the counter.

Break when the hit count is a multiple of the counter. Like “Modulo.”

Break when the hit count is gr


greater than or equal to the counter.

The loop below will now break when “i” is equal to 0, 3, 6, 9.


Notice we have a breakpoint defined and that the intellisense explains the b
breakpoint.
reakpoint.
Note that we hit our breakpoint.

Note that the “Breakpoints” window can tell you the current state.
If your computer is crashing…

You can set the “hit count” to a very large number and when your software crashes you can
see the loop count to get an idea where your software is crashing.

Conditional Breakpoints

You can specify


fy a breakpoint condition which will be evaluated when a breakpoint is
reached. The debugger will break only if the condition is satisfied.

To specify a breakpoint condition

In the Breakpoints window, right


right-click
click the line containing a breakpoint glyph and choose
Condition from the shortcut menu

In a source, Disassembly, or Call Stack, right


right-click
click a line containing a breakpoint glyph and
choose Condition from Breakpoints in the shortcut menu.

In the Breakpoint Condition dialog box, enter a valid expression in the Condition box.

Choose is true if you want to break when the expression is satisfied or has changed if you
want to break when the value of the expression has changed.

Click OK.
“Has Changed” means it will break if i changes.

To enable a condition, the Condition checkbox must be ticked.

A condition expression may then be entered into the textbox.

Two types of condition are permitted.

An "Is true" condition specifies that the expression in the textbox must be met in order
for execution to be paused. If, when the code reaches the breakpoint, the condition does
not evaluate as "true", the code will continue as normal.

A second type of condition is the "Has changed" expression.In this case, when the
breakpoint is hit, the value of the expression in the textbox is compared with the value of
the expression on the previous occasion that the breakpoint was encountered. Only if the
value has changed is execution paused.
Unselecting the “Condition Checkbox” allows you to return back to an regular,
“unconditional” breakpoint.

Note: You can combine a “Hit Count” and “Conditional” breakpoint at the same time.

Using methods for conditional breakpoints

We will use the AssertExample class when doing “Conditional Breakpoints”


Now run the code. Essentially, we will hit the breakpoint when CheckName()re
CheckName()returns
turns the value
of true. Also notice that intellisense is working.

From the menu select Debug, Start Debugg


Debugging.
ing. Here you can see that the debugger stopped
only on the second breakpoint because we tried to assign null to the name property. Being
able to call functions from the conditional breakpoint window can be very useful as you have
seen in this example. Essentially, this feature allows you to directly program the debugger
and can be used in complex debugging scenarios.
Debugging
gging in a multithreaded environment is very difficult. The same challenge exists on multi-
multi
CPU Machines as well.

Conditional breakpoints are for breaking at the expression level, when a particular condition is
true, like x=5. But what if you have multipl
multiple
e instances of the same app running? How do you
set to break the instance you want?

Filter breakpoints need to be enabled on the tools menu. Go to Tools – Options – Debugging –
General, and there you’ll see the option to enable breakpoint filters.
Lesson 4 – Debugging Threads

Threading Primer

Threading is a complex topic. Parallelism is another word used to describe the concept of
running code in parallel. Understanding threading is an important first step to following this
tutorial.

Unless very carefully designed, multithreaded programs tend to be unpredictable, hard and
to test, and hard to get right.

Waiting for something to happen is something that threads need to do frequently.


Whenever you read user input or access a disk, your thread must wait. Because the disk
drive and the user are millions of times slower than the processor, waiting for something
that applications need to do is something we need to be very good at. Specifically, we need
a way to wake up certain threads when other threads exit. Since the operating system is
responsible for thread shutdown, it seems reasonable that the operating system would be
able to tell other threads when a given thread shuts down. We will do this programmatically
with the examples below.

There are many different types of threads:

Type Synchronizes access to code regions.


Mutex Same as Lock/Monitor but can work system-wide.
Interlocked Use when performing atomic arithmetic operations and comparisons. Avoid dirty read
scenarios.
Read—Writer Useful when there are many read-only threads but fewer writer threads.
Semaphores Controls the number of threads that can access a resource at any point in time.
EventWaitHandle Threads participate in synchronization by signaling each other.
In order to make sense of some of the debugging features, I am providing a brief tutorial on
threading topics. Nearly all computers today come equipped with either multi-core
multi or multi
CPU configuration. More than ever is important to architect applications that take
t
advantage of threading approaches. The biggest challenge to writing code that utilizes
threads is getting them debugged and working correctly. As a field engineer I noticed that
most performance issues both on the server and on the client related to broken threads.
Sometimes threads get deadlocked other times they spin endlessly waiting for a resource to
free and sometimes that resource never gets freed.

EventWaitHandle() & EventResetMode.AutoReset

I encourage you to download the project below and ru


runn it to see exactly how it works. This
sample covers the AutoReset method of context switching between threads.

Click here for the download

EventWaitHandle() & EventResetMode.ManualReset

I encourage you to download the project below and run it to see exactly how it works. This
sample covers the Manual method of context switching between threads.

This example was also included in the previous download link, but here it is again for your
convenience. The best way to understand both the threading examples is to download and
run
un them. The two examples will show you the difference between a manual reset and auto
reset.

Click here for the download

Enabling Source Code Support

Before debugging threads, we need to tell Visual Studio to enable source code debugging.
This is easy to do. Just go to the Tools menu and select Options.. Navigate to the debugging
area and check the following boxes as seen below:
To get things started, we will say debug
debug,, start debugging. Next we will hit the button whose
caption reads create threads. At this point 5 threads have been created, each one is blocked or
in a wait state. Now we wish to break in to the debugging session by going to the debug menu
and selecting break all.

To start things off where we’ll start debugging the application as you can see in step one. Next
we will click the create threads button in step two. In step three select the break all menu
selection from the debug menu.

At this
his point, we would like to see which threads are operating inside of our application. That is
what the threads window is used for. So display the threads window.
All 5 threads can be seen above. All of them are started but are in a “wait” state. They are
blocked at this time.

The goal

With five threads running setting a breakpoint becomes challenging. It may become
necessary to want only one of the threads to hit the breakpoint. Notice in the debugger
threads window, each thread has an ID. It is with this ID that we can tell the debugger to
break for a specific thread.

Step 1:: Set a breakpoint as seen below

Step 2: Run the application. The debugger output window will display the thread numbers.

Step 3:: Right click on breakpoint and set a “Filter” on one of the threadnumbers.

Step 4:: Go back to the main form of the application and choose “Close Threads”.
We will start by setting
ing a generic breakpoint inside of our code. Once that is done we can
apply the breakpoint filter.

At this point we can just choose any one of our worker threads. We will choose thread
number 1828 just for their heck of it.

By right mouse clicking on the breakpoint we can choose the filter menu item. Notice that
this dialog box allows us to specify a machine, the process, and a thread, by either ID or by
name, we will simply type in thre
thread ID equals 1828.
At this point we’re ready to continue. So go to the debug menu and select continue.
continue At this
stage the applications threads are in a wait state (meaning they are blocked on the
waitHandle.WaitOne()
Handle.WaitOne() code statement). But if we go to the applications in main form and
choose close threads, they will become unblocked and therefore the threads will be allowed to
continue to execute. However, only thread 1828 will hit the breakpoint becau
because
se that is what
we specified in the breakpoint filter modifier.
But that is the big take away and this lesson. Being able to hit a breakpoi
breakpoint
nt for a specific thread
is critical when debugging.

The Art of Debugging – A Developer’s Best Friend – Lesson


5 – Using TracePoints - Repost
TracePoints
Tracepoints are a new debugger feature in Visual Studio. A tracepoint is a breakpoint with a custom action
associated with it. When a tracepoint is hit, the debugger performs the specified tracepoint action instead of, or
in addition to, breaking program execution.

We’ll start by setting an ordinary breakpoint in the following e


event
vent procedure. Next, we will right mouse click
on the break point and select “When Hit

Notice that the dialogue box that comes up and allows us to perform two basic tasks. One
thing that we can do is to print a message. Another thing that we can do is to run a macro.
Continue execution simply means that youyourr code will continue to run after performing the
task that you specified. Notice that when you print a message there are a lot of valuable line
items that you can display. For example, you can display the callstack, the process ID, the
thread ID, etc.

We can also add our own variables to the “print a message” section of the “when breakpoint
is hit” dialog box. For example, the this keyword refers to the currently executing form, and
if we want to display the public properties of the form we will add tthe
he following code to our
dialogue box text: this={this}.
Simply open up the output window to see the result.

The output
Function: CSBreakPoints.MainForm.buttonAssertExample_Click(object, System.EventArgs),
Thread: 0x2014 Main Thread this={CSBreakPoints.MainForm, Text: C# Breakpoints Demo}
Demo
Pam

Notice that in addition to the function name, the thread ID, and the thread name, we
also displayed the results of our this object, which printed the text property for the
main form.
The Watch Window (AKA Expression Evaluator)

The Watch window is one of the finest piec


pieces
es of software engineering you'll see

It offers almost infinite flexibility

The most important thing is that in the Watch window and its cousins (Autos, Locals, Quick
Watch, etc) you can click on the value of a variable and change it

The awesome new data tips


ips are the Watch window in tool tips

All data is fully editable

Pressing the CTRL key makes the Data Tip window see through

Demo

Open source code to MainForm.cs and navigate to XmlManipulation method and set a
breakpoint on the “XmlElement myElement = doc
doc.DocumentElement;” line.

Switch to the C# Breakpoints Demo window and click the Default Views button. Move the
mouse to the “doc” value on the doc.LoadXml line.
You can make direct modifications to variables through the data tip window. As you can see
here, I went to the InnerXML element and modified the title of the book.
Lesson 6 – Watch and Immediate Windows – Advanced Techniques

Calling Methods in the Watch Windo


Window

The watch window is incredibly powerful. You can actually call methods directly from this window.
But note that that method call must execute within 20 seconds, or visual studio will assume that the
method is hung and will cancel its execution
execution.

Open source code to MainForm.cs and navigate to buttonWatch


buttonWatchDemo_Click
Demo_Click method and set a
breakpoint on the "CallABunchMethod()" line
line.

Switch to the C# Breakpoints Demo window and click the Call A Bunch button.

After setting a breakpoint, go ahead and start debugging. At this point, we are ready to bring up the
watch
ch window. The watch window is available from the debug menu. Notice that there are up to
four separate watch windows you can choose from.

Before we actually execute them that could from the watch window, let’s actually go and see what
the method looks like. Notice that the method simp
simply
ly prints out messages to the output window.
Depending on the result of the modulus operator we print different messages.
Notice that we’ve got full intellisense available. In this case we want to execute
CallABunchMethod(). So select ct the method from the intellisense and hit the enter key. You’ll need
to remember to add the parentheses however.
Notice that the output window is displaying the appropriate message –namely, that we have not hit in
the value of five in our static variable. One thing to remember is that if we want to call this method
more than once through the watch window, we need to erase it and re re-type it.

The Immediate Window

ers similar capabilities. It should be familiar to those who have


The immediate window also offers
previously programmed in Visual Basic 6. You start all commands with a question mark as follows:

You can also execute methods from the immediate window. One thing to note is that break points
are disregarded in the watch windows while breakpoints are adhered to in the immediate window.
That means that if you set a breakpoint
akpoint within a function call the debugger will stop there if you
execute that method through the immediate window. The same is not true for the watch windows.

Another difference between the immediate windows and the watch windows is that method calls
from
rom the immediate windows can last as long as you wish them too. However, in the watch windows
you only have 20 seconds two finish executing the method before the debugger abandons the call.
call
Using the watch window to help you do find test case
cases

The watch window allows you to a modify data directly. In the window below you can see the
condition in the if statement. Currently it is a true statement. In order for me to make it a false
statement I have to step through the debugger some more. But what I can do instead is change the
static variable directly within the debugger to see the effect it has on the condition within the if
statement.

Now I can go to the value column in the watch window and type in the number “1”. This will cause
the condition in the if statement to become false. This gives me a quick and easy way to test my if
statements without having to do endless stepping through the debugger.
This is a real straightforward way to change the state of my application without having to constantly
re- run the application, testing various conditions during each run. This is a real big time saver. It
also allows for
or easy test case generation. Scripting languages have had this for a while, but now we
can take advantage of it for managed code as well
well.

How to create and replace a local object from the watch window or from the immediate window
windo

Similar to the way we callll the methods from the immediate and watch windows, we can also create
objects, replacing existing objects within the stack frame.

Notice that we are about to pass a null populated object to the method called CallEvenMore().
Hitting the F11 key (single step) in the debugger end
ends up passing the ae object to the method called
CallEvenMore().

Notice that in the function above, the AE object is in fact equal to null. Before single stepping one
more time, we want to inject a new object called the x, except that we will not put in a null value –
instead, we will populate this object with a real value
value.

This new object will appear in the locals window, preceded by the symb
symbol “$”.

Using standard c# syntax, this can be done from the immediate window as follows:
Now, we can assign this $x variable to ae, allowing us to directly use the ae variable within the
CallEvenMore() method. This is a useful technique which allows you to create new variables or
objects on the fly. As you can see, we were able to test the strin
stringg method called IsNullOrEmpty()
without having to run the application multiple times. We simply created a new variable on the fly
and assigned it to a local variable within the method, all from the immediate window.
Lesson 7 – Advanced Techniques – Using Object ID

Make object ID – allows you to track an object within the visual studio debugging system

When debugging native code, it's easy to keep track of objects by their addresses.

But, with managed code, you don't really have this option. Everything is a reference in managed
code. Address is simply are not relevant and managed code.

This can make it hard to tell keep track of objects.

But, when debugging in Visual Studio (at least 2005/2008), you can right click an object and select
"Make Object ID".

This will put a number like {1#} after the object.

You can do this on as many objects as you want to track.

I find this really useful in investigating a bug that involved some nasty recursion and reentrancy.

Let’s look at a demo.

Note that in the code below we have set a breakpoint. If we hover the mouse over the doc variable,
data tips will popup. Next, you can right mouse click and a context menu will appear, with Make
object ID as one of the options. A few Daugherty

Notice that 1# has appeared to the right.


What makes object ID particularly interesting is that you can look at objects or variables even if they
are out of scope.

Essentially, object ID is making objects or variables visible throughout the execution of your
application, regardless of scope.

Let's test this.

Start by adding the doc variable as well as 1# in the watch window.

Next we will run the application and set a breakpoint where the doc variable is not in scope.

Notice that in the watch window the doc is grayed out while 1# is visible, even though the doc
variable is completely out of scope.

Furthermore, notice that the 1# retains its most previous runtime value. This can be an important
feature if the execution path changes based on the value of a variable or object.

The bottom line is that you can observe your variable or object as it moves through the system.
Imagine a scenario where you have an array of objects that all exercise the same methods. But
you want to break only when a specific object invokes a method.

Download the source for Array of Cars


Start by setting a breakpoint on the for each loop.

Start the debugger and run the application until it hits the for each loop. Once you hit the breakpoint at
the fort each loop you can assign an object ID to one of the car objects.

Notice that I am right mouse clicking on the second array element of cars. I am making an object ID out
of the convertible car object.

Notice that 1# has been assigned to the convertible car.


Now we can go to the car class and set a breakpoint within the method called DescribeCar(). Once you
have set the breakpoint, right mouse click on it and select condition.

Notice that the condition sets the this object to the newly generated object ID of 1#.

This means that the breakpoint will only be hit when the invoking object of the DescribeCar() method is
a convertible car.
Notice the + within the breakpoint indicates that this is a conditional breakpoint.

From the menu select debug| continue at which point the breakpoint will be hit.

Notice that our conditional breakpoint functioned correctly.

Notice the invoking object is in fact the convertible car.

This is a very powerful technique in situations where you have large numbers of objects and you want to
break on method calls for only one specific instance
Lesson 8 – The Garbage Collector

Garbage collection in the Microsoft .NET common language runtime environment


completely absolves the developer from tracking memory usage and knowing when to free
memory.

However, you'll want to understand how it works.

It is important to know how resources are allocated and managed, and how the garbage
collection algorithm works.

How the garbage collector identifies objects to free from memory

The garbage collector checks to see if there are any objects in the heap that are no longer
being used by the application.

If such objects exist, then the memory used by these objects can be reclaimed.

If no more memory is available for the heap, then the new operator throws an
OutOfMemoryException.

It is not trivial for the garbage collector know if an application is using an object or not.

When you use the new operator

Each time you use the new operator to create an object, the runtime allocates memory for
the object from the managed heap.
As long as address space is available in the managed heap, the runtime continues to allocate
space for new objects.

One memory gets low

Memory is not infinite.

Eventually the garbage collector must perform a collection in order to free some memory.

The garbage collector's optimizing engine determines the best time to perform a collection,
based upon the allocations being made.

As stated previously, when the garbage collector performs a collection, it checks for objects
in the managed heap that are no longer being used by the application and performs the
necessary operations to reclaim their memory.

The garbage collector improves performance by using generations

One feature of the garbage collector that exists purely to improve performance is called
generations.

A generational garbage collector takes into account two facts that have been empirically
observed in most programs in a variety of languages:

Assumptions made by the garbage collector

Newly created objects tend to have short lives.

The older an object is, the longer it will survive.

How the garbage collector groups objects

Generational collectors group objects by age and collect younger objects more often than
older objects.

When initialized, the managed heap contains no objects.

All new objects added to the heap can be said to be in generation 0, until the heap gets filled
up which invokes garbage collection.

As most objects are short-lived, only a small percentage of young objects are likely to survive
their first collection.
Surviving collection and moving to the next generation – generation 1

Once an object survives the first garbage collection, it gets promoted to generation 1.Newer
objects after GC can then be said to be in generation 0.The garbage collector gets invoked
next only when the sub-heap of generation 0 gets filled up.

All objects in generation 1 that survive get compacted and promoted to generation 2.

All survivors in generation 0 also get compacted and promoted to generation 1.

Generation 0 then contains no objects, but all newer objects after GC go into generation 0.
What developers should care about

It is better to have your objects in lower generations, such as generation 0 or 1. That way there
is a higher likelihood that they will be collected and memory will be freed.

The purpose of this blog

While all the background? Knowing which generation our objects reside in is a big help.

Knowing that our objects on not being garbage collected is critical to managing memory
efficiently.

That is the main function of this part of the blog.

Currently, there is no built in way to determine the generation of an object that needs to be
collected.

Our goal – to determine the generation of the “bytes” as it’s array

The .net framework contains a class called GC. This might be a good starting point to determine
which generation our object is in.

Notice below that we are building a string builder object. It is called SB. We would expect that
this object is in generation zero right after we step over its allocation in the debugger.

There is a method in the GC class called GetGeneration. This method takes as a parameter the
object whose generation we wish to determine.

We can do this directly from the watch window.


Notice that intellisense allows us to select the appropriate method.

As we would expect, the sb object is in fact in generation 0.


Notice that we can also apply our object ID is that we previously defined.

Recall that this object referrers to our main form.

Notice that it is now in generation one, meaning is survived the sweep by the garbage collector.

Too many objects in higher generations can lead to real performance problems.

Too many objects in generation two, for example, can cause the garbage collector to work too
hard during low memory situations.

Your application may experience lots of disk swapping and high CPU utilization in this situation.

This may cause your application to the CPU starved and it will perform poorly.
The goal of this blog was to teach you more about the garbage collector.

And despite the fact that the built in debugger doesn't provide useful generational information,
I have provided the means by which you can determine which generation your object resides
in.

Lesson 9 – The Set Next Statement

If you are not familiar with the Set Next Statement feature, it allows you to specify from
which line of your application's code you wish to resume running.

Please be aware that setting the next statement can be dangerous.

It is easy to skip over critical code (ex: object creation, variable initialization, etc) and lead to
unexpected application behavior and/or crash your application.

There are some limitations on which lines you can specify as the next statement: You cannot
set the next statement outside of the current method You cannot set the next statement
into a catch or finally block If you cannot set the next statement to your desired line, Visual
Studio 2008 does an excellent job in letting you know why.

For example, attempting to set the next statement outside of the current method will cause
Visual Studio 2005 to display the following message.

Unable to set the next statement to this location.

In the next sample, we will force in a statement to evaluate to true. We can do this in one of
two ways. The first way is to simply drag the yellow arrow. The second way is to right
mouse click on the line of code that you wish to execute.
As stated previously, you can also set the next statement with a simple right mouse click.
This approach makes more sense if the function is quite large. Dragging the arrow on a very
large function may be impossible.

Underneath the hood it is actually quite simple what the set next statement is really going.

It simply changes the instruction pointer.

If you know anything about assembler this is quite trivial.

But you should exercise caution

You may inadvertently skip over a key object initialization. This may cause a null reference
exception later in your code.

Can you jump to other functions?

The answer is no. The reason is that the runtime may have not jitted the code for that other
function. Therefore, changing the instruction pointer is impossible.

Can you go backwards?

Yes you can. This might make sense in a scenario where you wish to initialize an object to
manually by moving forward and backwards as needed.
Lesson 10 – Debugging Threads

This next section is fairly brief and will help you work with the debugging of threads more
effectively.

The the feature all I am about to show you is off by default.

It is available from the toolbar so as a first step we need to bring up the debug toolbar.

Right mouse click at the toolbar area and select debug.

The next step is to enable the option “show threads in source.” Once again that is available
from the debug toolbar. It is not enabled by default, therefore we must switch it on.

To test this option we will create our threads and then enter break mode. Select the “create
threads” button below.
Next, we will select “Break All” from the menu.

Because we have enabled source code debugging, we will end up in some .net system source
code.

We need to switch windows back to our own source code. We can do this with a simple control
tab. Notice the squiggly lines in the gutter. If we hover our mouse over the squiggly lines we
can see exactly which threads are awaiting to be signaled.
Notice we can see that five threads are awaiting on the method call WaitOne().

As the next step,let’sbringupthethreads debugger window. You can find this in the Visual
Studio menu Debug | Windows | Threads.
Notice that we can hover the mouse over one of the thread’s location columns and get the call
stack for that thread. For example, below we are looking at thread 3’s call stack.

You also have the option of renaming the thread the right from the debugger using a simple
right mouse click.
Big challenge for developers – single stepping through a thread’s execution

Because windows is a preemptive operating system, the context switch to another thread may
be forced upon you buy Windows. This can interfere greatly with your debugging session. The
solution to this problem is to suspend the other threads so that the thread you are debugging
does not get interrupted by the operating system.

That means you can control click and select all the threads that you wish to suspend, right
mouse click and choose the freeze option as you see above. Freeze is the same thing as
suspend.

You can also thaw your threads


Notice that in the second column of the threads window, four of our threads were suspended.
But I can re-select act the suspended threads and get them to resume by right mouse clicking
and selecting thaw.

Lesson 11 – SQL Server Stored Procedures

This section of my blog is to illustrate how visual studio can be used to debug stored
procedures in SQL Server. Luckily, most of the commands are identical and the learning
curve is trivial. Let’s get started.

We will use Server Explorer to attach to AdventureWorks.

In this blog we will add a new stored procedure. We will execute the stored procedure. We
will step through the stored procedure and use traditional debugger commands that have
been discussed in the previous 10 blogs.

These are very powerful techniques and are dramatic time savers. You can also use these
techniques to help you discover how other store procedures were written by other
developers.
Begin by going to Visual Studio’s View menu and selecting Server Explorer.

Right mouse click on Data Connections and select Add Connection.

Notice that our AdventureWorks database is already contained or hosted by SQL server
2008. This is the instance that we wish to connect to and debug.
Click on the change button and make sure you select Microsoft SQL server as the data
source type.

When I tried to connect directly to the SQL server database file, the .mdf file, I got an error
indicating versioning problem.

I recommend connecting to the database instance posted within SQL server.

This is a more realistic scenario anyway.


After entering localhost for the server name, you’ll see a drop down list of the available data
bases. Select the AdventureWorks database and click OK.
In this example we will add to a stored procedures.

The first store procedure will contain some simple selects.

The second stored procedure will contain some business logic allowing us to test the
debugger more complex scenario
Name of stored procedure = uspGetList

Download the stored procedure here - sp_uspGetList.sql

Within server explorer right mouse click and stored procedures and add new stored
procedure.
Paste in the stored procedure code then select file save.

Notice the stored procedure appears in the server explorer to the left, highlighted in blue.

The first select statement choose


choosess those products whose list price is less than the maximum
price.

The second select statement chooses the maximum list price for a given product that is less
than the maximum price passed into the stored procedure.
Running [Production].[uspGetList] ( @Product = %Frame%, @MaxPrice = 500, @Co
@ComparePrice
mparePrice = 350,
@ListPrice = 400 ).

To start
tart the debugging session, right mouse click on the stored procedure and Select Step
Into Stored Procedure.
You will now be able to use the F10 and F11 keys to step through your stored procedure
code.
A dialog box will appear that allows you to provide parameters for your stored procedure.

Notice the yellow arrow indicates the current line of execution.

You can hover the mouse over variable names to determine their value.

Notice that I added a little if statement.


Many of the same techniques that I've discussed in the previous 10 blogs apply debugging
SQL server stored procedures.

Notice that the locals window is there, the output window is there.

This concludes the tutorial on using Visual Studio 2008 to debug of SQL Server Stored
Procedures.
Lesson 12 – Debugging Javascript In Web Pages

The first step is to enable debugging within the browser.

Be sure to allow for script debugging. To do this, start Internet explorer and select from the tools
menu. Click on options. Navigate to the advanced tab and make sure the checkboxes in the red
box art deselected.
Within the Visual Studio Solution Explorer, make sure that your web project is the startup
project.
Once you have made your web project the startup project, now you will define which web page
is the start page once you start the debugger.

Start the debugging process by selecting step into, which is the F11 key.

You may be asked to modify the configuration file to enable debugging. You should obviously
select yes.
Notice that the instruction pointer has begun running the JavaScript. That this did you can easily
single step or step over the code.
The various windows that we discussed previously can be used.

You can see in the JavaScript code above the value of the mydate variable.

Method #2 – To Debug Javascript

The next approach to debugging launches the debugger directly from within Internet explorer.
The way this is accomplished is by using the view menu once the web page is loaded. From the
View menu select View Script Debugger.

In this example we will select Break At Next Statement.


Your web page will now sit and wait state until JavaScript gets executed. In this case, clicking on
the button will initiate some JavaScript. At that point we will be prompted with the opportunity
to choose our debugger. We will choose Visual Studio.

Choose yes in the dialog box below.

At this stage we are asked which debugger we wish to use. Since visual studio is the most
powerful debugger, we will select Visual Studio. We will select new instance of Visual Studio
2008, since we do not want to interfere with the existing instance of visual studio already open
which is running the solution called CSBreakPoints.
Notice that the bug are brought us appropriately to the onclick event.
Step into the code with F11 key. This technique will cover most of the debugging scenarios that
you encounter.

We hit the F5 or continue debugging command to finish running the JavaScript. You can see the
result below were appropriately.

Lesson 13 – Debugging VBScript

1: dim filesys
2: dim step_number
3: dim trg, src
4:
5: step_number = "04"
6:
7: set filesys=CreateObject("Scripting.FileSystemObject")
8:
9:
10:
11: src = "c:\devprojects\azure\labs\BuildingWindowsAzureServices"
12: trg = "C:\livedemos\Azure\HelloWorld\step" & step_number
13: If filesys.FolderExists(trg) Then
14: filesys.DeleteFolder trg, true
15: end if
16: call Generatepath(trg)
17: wscript.echo "Copying " & src & "...."
18: 'filesys.CopyFolder src, filesys.GetParentFolderName(trg) & "\"
19: filesys.CopyFolder src, trg & "\"
20:
21:
22: Function GeneratePath(pFolderPath)
23: GeneratePath = False
24: If Not filesys.FolderExists(pFolderPath) Then
25: If GeneratePath(filesys.GetParentFolderName(pFolderPath)) Then
26: GeneratePath = True
27: Call filesys.CreateFolder(pFolderPath)
28: End If
29: Else
30: GeneratePath = True
31: End If
32: End Function

Debugging VBScript is incredibly easy. This will no doubt be the most straightforward and
simplest way to debug code of all the previous blogs.

I recommend by starting with an administrator level command prompt. If you are a developer
and not an end user, running as an administrator is recommended for most operations.

One of my favorite editors is VI. Below you can see a bunch of VBScript code that we wish to
debug one line at a time.

To make my life easier I will navigate to the c:\livedemos\q3fy09\draft\azure folder and


execute the VBScript below using a debugger.
You can begin this lesson by starting a command prompt as administrator.

Notice my command prompt window below. Also notice my VBScript file waiting there to be
executed. Let’s go ahead and run that script in the debugger.

If you ever forget the syntax, you can just execute cscript /?.

Cid added the secret to debugging.cscr using our example simply type in cscript /x /d
MakeSteps.vbs
Here is the results of our command.

Select a new instance of Visual Studio.


Simply use the debugger commands previously described in the blogs.

You might also like