Power Debugging

advertisement
Advanced .NET Debugging
John Robbins
john@wintellect.com
what we do
Consulting | Debugging | Training
who we are
Founded by top technical and business experts, we are a fast-growing
group of outstanding consulting and training professionals who pull
out all the stops to solve their clients’ problems.
how we do it
Consulting & Debugging
Training
- Architecture, analysis, and design services
- Full Lifecycle custom software development
- Content creation
- Project management
- Debugging & performance tuning
- On-site instructor-led training
- Virtual instructor-led training
- Devscovery conferences
About the Presenter – John Robbins
• Email: john@wintellect.com / v-jorobb@microsoft.com
• Blog: http://www.wintellect.com/wintellog.aspx
• Co-founder of Wintellect
– A consulting and education firm dedicated to helping clients ship better software
faster
– Concentrate on debugging impossible bugs
• Author
– Debugging Microsoft .NET 2.0 Applications, Microsoft Press, 2006
– Debugging Microsoft .NET and Microsoft Windows Applications, Microsoft Press,
2003
– Debugging Applications, Microsoft Press, 2000
– MSDN Magazine Contributing Editor and Bugslayer Columnist
• Formerly worked at NuMega Technologies-Engineer, Architect, and Product
Manager
–
–
–
–
–
BoundsChecker (versions 3.0, 4.0 and 5.0)
TrueTime (versions 1.0 and 1.1)
TrueCoverage (version 1.0)
SoftICE (version 3.24)
TrueCoverage for Device Drivers (version 1.0)
Session Code
• Download all the stuff mentioned in class
– http://www.wintellect.com/downloads/DotNetDebuggingCode.zip
Prerequisites
• Build both Debug and Release builds with PDB symbols
– Debugging at the assembly level gets old quick (unless you get
paid by the hour!)
• Set up a company symbol server to hold your PDB files
– msdn.microsoft.com/msdnmag/issues/02/06/Bugslayer/
– Will always keep your symbols lined up
• Set up each machine you touch to at least use the public
Microsoft symbol servers
– See my Set-VS2010SymbolServer.ps1 script in the session code
Turn off Just My Code
• The “feature” is to isolate your debugging to only code that
is built non-optimized and/or has no debugging symbols
• In real world development, it hides way too much from you
• Disable in Tools, Options dialog, Debugging, General
property page
Setting Debugging Properties
• Project Properties Debug property page
– You can set
• Command line arguments to pass to the application
• The working directory of the application
• If you want remote debugging
• Native, SQL, and hosting options
What’s that VSHOST thing?
• Makes debugging faster by loading your binary into an
already running process
• Allows partial trusted debugging and design time
expression evaluation
• Be aware
– AppDomain.CurrentDomain.FriendlyName and
Assembly.GetCallingAssembly().FullName will return different
values when running under the host process
• Disable in the project properties, Debug page, by
unchecking Enable the Visual Studio hosting process
Debugging Partially Trusted
• Now super simple with the Security tab in the project
properties
• Enable ClickOnce Security Settings
• Select the exact permissions your application needs
• All debugging will be done with those permissions
• Any security exceptions will suggest what you need to fix
Debugging EXE Programs Without
Compiling
• To open an EXE to debug by itself
–
–
–
–
From the File, Open, menu, select Project/Solution
Browse to the EXE directory in the Open Solution dialog
In the Files of Type combo box, select All Project Files
Open the EXE
• You now have a solution with just the EXE
– Open source files for the project and set breakpoints just like
normal
Debugging EXE Program without
Compiling
• The type of the EXE determines what debugging will be
done
– If it’s a native EXE, native debugging is the default
• To change
– Right click on the EXE and select Properties
• The dialog is actually the native debugging property page
– Change the Debugger Type combo box
• Auto = based on EXE type (the default)
• Mixed = both managed and native at the same time
The .SUO Problem
• All settings like breakpoints, Watch window values,
window layouts, and exception settings, are stored in a
hidden file,
<Solution Name>.SUO
• Occasionally, this file can become corrupted and lead to
serious problems
– Problems caused by corrupt .SUO files
• Breakpoints no longer hit
• Crashes attempting to display Watch windows
• Exception stopping no longer works
• Visual Studio crashes when loading a solution
• If Visual Studio is flaking out in any way
– Delete the .SUO and that will probably clear up the problem
– Get in the habit of saving your breakpoints!
Advanced Breakpoints
• In the debugging dark ages, you had to run your program
until it crashed and look at a hex dump listing because
there were no breakpoints
• The debugger renaissance age allowed you to set a
breakpoint on an address and view a disassembly
• In the debugging modern age, setting a breakpoint on a
source line was something magical
• The post-modern age of debugging is all about Advanced
Breakpoints
Before Setting Advanced Breakpoints
• Always start debugging first
• If you are not debugging, only Intellisense is used to
determine the breakpoint
• Once debugging, you have both Intellisense and symbol
tables
Breakpoint Window Codes
Glyph
Meaning
Normal breakpoint [enabled and disabled]
Advanced BP (hit count, condition, filter) property set
Mapped BP in ASP/ASP.NET and mapped to an HTML page
Normal tracepoint
Advanced tracepoint (hit count, condition, filter) property set
Mapped TP in ASP/ASP.NET and mapped to an HTML page
Breakpoint or tracepoint error (the BP or TP will never be set)
Breakpoint or tracepoint warning (generally means the source location
is not currently in any loaded module)
Location Breakpoints
• Right clicking in the margin or pressing F9 on a line sets
what's called a location breakpoint
• The breakpoint does not trigger until that location
executes
• .NET does not support data breakpoints like native code
Advanced Location Breakpoints
• Don't forget about Run to Cursor
–
–
–
–
You can set one-shot breakpoints with it
While debugging, right click on the line and select Run To Cursor
Default keyboard keystroke: CTRL+F10
If you're not debugging, you'll start debugging and run to that
location
Advanced Location Breakpoints (cont.)
• Select the location up the stack you want to stop on
– Press F9 to set a breakpoint
– If you right click on the stack item, you can also choose Run to
Cursor
Sub Expression Breakpoints
• You can easily set breakpoints on sub expressions on the
same line
• Clicking the margin only sets a breakpoint on the first sub
expression on the line
• Select the sub expression you want to stop on and press
F9
– Only that sub expression will be highlighted as a breakpoint when
debugging
• The Breakpoint window shows the character start of the
sub expression
Sub Expression Breakpoints
• When you stop on that sub expression, it will be
highlighted yellow
• Clicking in the margin clears the breakpoints in character
order
Quickly Breaking on Any Function
• Opening files and scrolling all over the place just to press
F9 on a line is a big waste of time
• The debugger is smart enough to hunt down your functions
for you
• The magic is all in the Breakpoints dialog
– CTRL+B on the default keyboard
Quickly Breaking on Any Function (cont.)
• In the Breakpoint dialog, Function edit control
– Type the class name and method/property to break on
– The name is dependent on the language
• Use “Module.Function” for VB and C#
• Use “Module::Function” for C++/CLI
– The name is case sensitive for C# and C++/CLI
– Check Use Intellisense to verify the function name
• If debugging will use Intellisense and the symbols to find the
method/property
– Set the Language combo box to the appropriate language
– Leave the column and line set to 1
• This sets the breakpoint on the first instruction in the
method/property
Choose Breakpoints Dialog
• The New Breakpoints dialog has even more smarts built
into it if a project is loaded
• Instead of typing in the complete class and method, try
just the method/property name
• If that method exists in any classes in the solution, the
Choose Breakpoints dialog will pop up
Choose Breakpoints Dialog (cont.)
• From the Choose Breakpoints dialog
– All methods of that name from all classes are shown
– Clicking the All button will set breakpoints on all of them
– Clicking the check box next to an item will set or clear it
• If you're debugging a Visual Basic project
– You can specify the parameters in the Breakpoints dialog to skip
the Choose Breakpoints dialog
• Unfortunately, unlike native C++, typing just the class
name will not pop up the Choose Breakpoints dialog with
all the methods and parameters
– Use the BreakpointHeler macros
Setting Breakpoints without Source
• Interestingly, you can set breakpoints on Framework API
functions
– Or any other assemblies you don't have source code for
• The reason why this is cool is that you can get stopped at a
known point in the application
• It's also a great way to learn about how things fit together
in the .NET Framework
Setting Breakpoints without Source
(cont.)
• Steps to setting breakpoints
– Bring up the New Breakpoints dialog
– Type in the fully qualified name of the method or property you
want to stop on in the Function tab, Function edit control
– Don't worry about case sensitivity
– For properties, prefix with "get_" or "set_" as appropriate
– Click the Ok button
– In Use Intellisense is checked, you'll get a message about
Intellisense not being able to set the breakpoint
• Press OK and your breakpoint will be set
Setting Breakpoints without Source
(cont.)
• Steps to setting breakpoints (cont.)
– Go to the Breakpoints window and verify the breakpoint has a red
circle next to it
– If its got a question mark or warning icon in it, the breakpoint is
not set correctly
Setting Breakpoints without Source
(cont.)
• In the Breakpoints window you might see something
interesting next to the breakpoint
– A “+”, indicating a root tree element you can expand
– May not always see it, more on this later
• What you're looking at are called "child breakpoints"
Setting Breakpoints without Source
(cont.)
• When you run your application, you'll notice you stop in the
bowels of the jitted assembly language
• Pull out the Call Stack window and you'll see how you got
there
• The number of child breakpoints correspond to the number
of overloads for that method
• These breakpoints are set again when you restart
debugging
Fun with the Find Combo Box
• If the Breakpoints dialog is too slow for you, use the Find
combo box on the toolbar
–
–
–
–
CTRL+D with the default keyboard (Edit.GoToFindCombo)
Enter the class and method/property
Press F9
This sets a breakpoint on that function/class
• If you enter just an overloaded method/property
breakpoints will be set on all of them
Fun with the Find Combo Box (cont.)
• You can open system header and project files from the Find combo
box
– Type in the filename and press CTRL+SHIFT+G (Edit.OpenFile)
– Press CTRL+SHIFT+G
• You can issue Command window commands from the Find combo box
– Enter ">" and the Find Combo turns into a mini Command window
– Neat Command window tricks
• Enter “>open ” or “>of ” (notice space) followed by the first letter of the
project file you want to open
• CTRL+/ (Tools.GoToCommandLine) fills in Find Combo Box with last
command executed
Location Breakpoint Modifiers
• These are the real power in the debugger
– The more you practice these, the faster you'll debug
• The idea is to make the debugger stop only when you want
it to stop
• In other words, the debugger only stops when you exactly
match your hypothesis
• Supports, hit counts, conditions, and filters
Breakpoint Hit Count
• Skips a breakpoint a specific number of times when
running full speed
• Conditions for skipping
– Equal to
• Stop only when hit count equals initial value
– Multiple of
• Stop every x times (think modulo)
– Greater than or equal
• Continues to stop after equaling initial count
Breakpoint Hit Count Steps
•
•
•
•
Set a location breakpoint
Right click on the margin red breakpoint dot
From the context menu chose “Hit Count...”
In the Breakpoint Hit Count dialog, combo box, select the
condition
• In the edit control that appears, set the number to skip,
etc.
• Click OK
Breakpoint Hit Count Steps (cont.)
• The Breakpoints window will show the total execution
count
• Use it to see how far you are in loops, etc.
• You can also reset the skip count back to zero at any time
by accessing the Breakpoint Hit Count dialog for the
breakpoint
Breakpoint Condition
•
•
•
•
Probably the modifier you will use the most
Stops when a conditional expression evaluates to true
Also, can stop when a variable changes
The source language determines the expression operators
– If Visual Basic, “<>” is not equal, etc
– If C#, C++/CLI, “!=” is not equal, etc
Breakpoint Condition Steps
•
•
•
•
Set a location breakpoint
Right click on the margin red breakpoint dot
From the context menu choose “Condition...”
In the Breakpoints dialog, ensure the Condition button is
checked
• Select the "is true" radio button to stop when the condition
is true
• In the edit control type the complete expression to
evaluate
• Click OK
Breakpoint Condition Steps (cont.)
• If you enter just a variable in the Condition edit control and
select the "has changed" radio button
– You can break when a variable value changes on that location
• Additionally, you can specify hit counts to stop on the
specific time the condition is true
• The Breakpoints window shows the condition for the
breakpoint
Be Careful Setting Breakpoint
Conditionals
• Given the following C# code:
int i = 0 ;
for ( i = 0 ; i < 10 ; i++ )
{
Console.WriteLine ( “i = {0}” , i ) ;
}
• What would happen if you set a conditional BP on the
WriteLine with the condition “i = 3”?
– Remember: “i == 3” is the correct condition for C#
• My guess would have been the conditional bug discussed
two slides ago
• Nope! You get stuck in an infinite loop!
• Isn’t that the coolest thing ever!?
What Does It Mean?
• The breakpoint condition is evaluated inside the running
application
– Not inside the debugger context
• What would happen if you try to call a method in the
conditional?
– The method call executes when evaluating the breakpoint!
• This is tremendous power; use it wisely
– You can really mess up your application
• Yes, you can copy a 3GB DB from a breakpoint
– You now can have assertions on the fly!
Assertions On the Fly
• With the ability to call methods, now you can have debug
only methods that return true when something’s wrong
• Using that method as a conditional means you’ll only stop
when that condition is met
• Essentially, this is like poking in an assertion check before
the statement
– But there’s no code changing
Assertions On the Fly (cont.)
• Add a method that returns a Boolean
– Returns true if there is a problem
• Surround the method with #ifdef DEBUG…#endif
– Can’t use [Conditional(“DEBUG”)] as that only works for void return
types
• Use the method in any BP condition you want to stop on if
the condition is met
#if DEBUG
public bool CheckName ( )
{
if ( null == m_Name )
{
return ( true ) ;
}
return ( false ) ;
}
#endif
Filter Breakpoint Modifier
• Easily set per machine, process, and/or thread
breakpoints
• Setting a Filter Breakpoint Modifier
– Set a location breakpoint
– Right click on the breakpoint glyph and select “Filter…”
– In the Breakpoint Filter dialog, fill in your condition
• Undocumented syntax
– “==“ is supported
– The machine/process/thread keywords are case insensitive
Tracepoints
• Basically breakpoints with a different name
– Intended to continue execution
• Custom actions
– Print a message (jam in a TRACE statement)
• Put variables in “{}” to evaluate
– “\{“ to print a curly brace, “\\” to print a backslash
• Special codes in tracepoint dialog
– Execute a VSA macro
The Watch Window (AKA Expression
Evaluator)
• The Watch window is one of the finest pieces 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 are the Watch window in tool
tips
– All data is fully editable
– Pressing the CTRL key makes the Data Tip window see through
– Pin the tips to the source code
Calling Methods in the Watch Window
• It's a great trick for two reasons
– It allows you to see data structures that the Watch window does
not display well
– You can also have assertions completely on the fly
• Every time you view a property, you're calling the getter
method in the Watch window
• Calling a method is as simple as adding the parenthesis
and any parameters needed
Calling Methods in the Watch Window
(cont.)
• Where does the method/property execute?
– In the debuggee
• There are a few rules
– Don't do anything more than reading memory
– The method must execute in less than 10 seconds
• Interestingly, this same restriction does not apply to methods
called by breakpoints
• Does not stop on breakpoints when called from the Watch
window
– If you want to stop, use the Immediate window
Great Testing Trick
• Drag the expression in a condition down to the Watch
window
• This allows you to evaluate and see exactly what variables
will trigger the condition you need
• An excellent trick for driving that code coverage as high as
possible
• I've changed my coding style to avoid function calls in
expressions to make this easier to evaluate
What If the Expression Uses Objects?
• For example:
if ( false == String.IsNullOrEmpty ( ae.Name ) ) ...
– How do you change the ae variable since it is an object?
– You could change the individual property, but sometimes you need
to change the entire object
• The Immediate window to the rescue
– Open the Immediate window
• Type in an expression to allocate an object
SomeClass x = new SomeClass ( ) ;
– Open the Watch window
• Add the variable you want to change to the Watch window
• In the Value cell, enter the variable prefixed with a ‘$’ sign
– From the above: $x
Data Tips/Watch Window Tricks
• Right click on the data tip to bring up a context menu
– Standard options of cut, copy, paste, adding the object to the
watch window and setting hex display
• Make Object ID is the very interesting option
– Tells the debugger to watch a particular object in memory no
matter where it goes
– Can ID the object with a number
• Use 1# in the Watch window for object one, etc.
– Allows you to watch objects even out of scope
– If it says “Can’t evaluate” that means the object has been garbage
collected
– Can even use the object id in conditional breakpoints
• Allows specific instance breakpoints
• C# only feature
What Generation is This Object In?
• Nothing’s stopping you from calling GC.GetGeneration in
the Watch window
• Even cooler!
– Use Make Object ID to watch an object that’s not in scope
– Pass the Object ID to GC.GetGeneration
• The expression evaluator handles it just fine
Watch Window Format Specifiers
• Like C++, C# lets you format the data display with “,<op>”
formatting after the item
Specifiers
Format
,d
Decimal integer
,h
Hexadecimal integer
,nq
String not bound by quotes
Watch Window Pseudovariables
• $user
– Shows account information for the current thread
• $exception (C# only)
– Automatically shown in the Locals window if the Exception
Assistant is disabled
Auto Expanding Your Own Types
• C# only: If your class has an overridden ToString method,
the debugger automatically uses it
– This alone will let you see much better information with no extra
work on your part
• The big magic is in DebuggerDisplayAttribute
– In System.Diagnostic namespace
• Now we need an Code Analysis rule that looks for either
– Overridden ToString
– DebuggerDisplayAttribute
– If neither found, triggers an error
Using DebuggerDisplayAttribute
• Example, a complex number class
– Contains the numbers in two private variables, _Real, and
_Imaginary
[DebuggerDisplay ( "{_Real}.{_Imaginary}i" )]
public class ComplexNumber { . . .}
• Anything inside “{}” is evaluated using the instance of the
class
• What’s even cooler?
– If a class does not have a DebuggerDisplayAttribute
• The debugger walks the derivation chain looking for the first
class that has one set
– If a base class has one, that one is used
Using DebuggerDisplayAttribute (cont.)
• Can be applied to anything other than a method
• Can call methods and access properties in the string
– Be careful because syntax evaluation can be different between
languages
– The following works in C#, but not Visual Basic
[DebuggerDisplay(“Object {count - 2}: {(flag) ? \"yes\" : \"no\"}”)]
– Visual Basic also does not support calling methods, C# does
Advanced DebuggerDisplayAttribute
• Accepts named parameters
– Name – The value to place in the name column
– Type – The value to place in the type column
• Example: a KeyPair class that sets the Name named
parameter to show the key in the Name column
[DebuggerDisplay ( "{value}" , Name = "{key}" )]
class KeyValuePairs
Advanced DebuggerDisplayAttribute
(cont.)
• Hiding fields and roots can make your Watch window
display much cleaner
• Use the DebuggerBrowseableAttribute to set state
– Never – don’t ever display
– RootHidden – Don’t display the proxy type, expand the array items
(more on this in a moment)
– Collapsed – Don’t expand the class, hide internal members
Advanced DebuggerDisplayAttribute
(cont.)
• Example: the complex number class where the fields are
returned by appropriate properties
[DebuggerDisplay ( "{_Real}.{_Imaginary}i" )]
public class ComplexNumber
{
[DebuggerBrowsable ( DebuggerBrowsableState.Never )]
private int _Real = 0;
public int Real
{ get { return ( _Real ) ; }
set { _Real = value ; }
}
. . .
Advanced DebuggerDisplayAttribute
(cont.)
• DebuggerTypeProxyAttribute tells the debugger to
instantiate a different class to display the type
– In general, use a private class inside the main type to handle the
display
– Will be rare you use this
• See the Using DebuggerDisplayAttribute example in the
documentation
Expanding Types with No Source
• Debugger supports expanding types even if you don’t have
source
– Through AUTOEXP.DLL in Visualizer directories
– Magic is Target parameter to DebuggerDisplayAttribute
[assembly: DebuggerDisplay ( "Count={Count}" ,
Target = typeof ( WebCaching.Cache ) )]
• See AutoExp project in the session source code
Default Visualizers
• Tired of not seeing your strings, HTML, and XML in a
normal format in the debugger?
• The default visualizers are here to help
– Click on the magnifier in the string type magnifier and choose how
you want to see the data
• A huge productivity boost
Custom Visualizers
• The killer reason for upgrading
• Allows you to simply write code to display types in a more
identifiable way
• Amazingly simple to write
• Amazingly easy to test
• Microsoft ships the DataViewManager, DataView,
DataTable, DataSet visualizers, WPF visualizer, and LINQ
SQL Queries in the box
Installing Custom Visualizers
• Globally for all users
– <VS Dir>\Common7\Packages\Debugger\Visualizers
• For individual users
– My Documents\Visual Studio 2010\Visualizers
• Only supports modal dialog visualizers
Writing Visualizers
• After you determine the type you want to display
• Create a class library
– Add references to
• System.Windows.Forms
• Microsoft.VisualStudio.DebuggerVisualizers
– Put those in using directives
• Add an assembly level attribute that describes the type
you’re interested in displaying
– You can have as many visualizers as you want in a single assembly
Writing Visualizers (cont.)
• Parameter 1: The visualizer type you are writing
• Parameter 2: The serializer to use
– VisualizerObjectSource is the debugger supplied serializer
– Can write custom serializers if you want
• Target named param: the type you’re providing a visualizer
for
• Desc named param: the display name of your visualizer
[assembly: DebuggerVisualizer (
typeof ( Wintellect.Visualizers.ImageVisualizer ) ,
typeof ( VisualizerObjectSource )
,
Target = typeof ( System.Drawing.Image )
,
Description = "Wintellect Image Visualizer" )
]
Writing Visualizers (cont.)
• Derive your class from DialogDebuggerVisualizer
• Implement the trivial Show method
protected override void Show (
IDialogVisualizerService windowService ,
IVisualizerObjectProvider objectProvider )
{
// This is all it takes to get the actual object from the
// debuggee address space into the debugger.
// How simple is that!?
Image dbgImage = (Image)objectProvider.GetObject ( );
// Create your dialog here..
// Show it.
windowService.ShowDialog ( form );
}
Writing Visualizers (cont.)
• Implement a test method you can test the visualizer
without the hassle of debugging Visual Studio itself
– Create a console app to call the test method
public static void TestImageVisualizer ( object itemToVisualize )
{
VisualizerDevelopmentHost visualizerHost =
new VisualizerDevelopmentHost ( itemToVisualize ,
typeof ( ImageVisualizer ) );
visualizerHost.ShowVisualizer ( );
}
Cool Free Visualizers
• Regular Expression Visualizers
– regex.osherove.com/Articles/RegexKit.html
• Dynamic IL Visualizer
– blogs.msdn.com/haibo_luo/archive/2005/10/25/484861.aspx
• ASP.NET Cache Visualizer
– http://blog.bretts.net/?p=11
• Mole Visualizer
– www.codeproject.com/KB/macros/MoleForVisualStudioEdit.aspx
– View anything with drill down
– Really nice for ASP.NET and WPF
Set Next Statement Command
• A cool hidden trick in the debugger
• It allows you to change the instruction pointer to a
different location
• A great debugging trick for two reasons
– You can drive your code coverage higher
– You can re-execute code to double check conditions
• Be careful, as Set Next Statement can easily crash your
program if you put the IP in the wrong place
Using Set Next Statement Command
• Select the yellow instruction arrow and drag it to a
different location
• Right click on an executing line when debugging and
choose Set Next Statement
Step Over Properties and Operators
• Debugger converts step into a property/operator into a
step over
– Looks at the code and if it’s small enough, does the step over
• Toggle on and off on the fly while debugging
– Right click in source code and select on context menu
Threads Window
• Always enable Show Threads in Source
– Turns on margin icon that shows you what other threads are
executing in the application
Threads Window (cont.)
• Can change the name of a thread in the Name column
– Right click on thread and select Rename
• Makes filter breakpoints much easier
• Freeze threads to avoid bouncing around when single
stepping
– Use the FreezeThawThreads macros to make it easy
• Use InterestingThreads macros to switch all breakpoints to
stop only on a specific thread
The .NET Reference Source Code
• Seeing the .NET source is wonderful when debugging
• Setting up your IDE
– In Options dialog, Debugging General
• Uncheck “Enable Just My Code (Managed only)”
• Check “Enable source server support”
The .NET Reference Source Code (cont.)
• In Options dialog,
– In “Symbol file (.pdb) locations” check
• Environment variable: _NT_SYMBOL_PATH
• Microsoft Symbol Servers
• Add “C:\SYMBOLS\PUBLIC\MicrosoftPublicSymbols*
http://referencesource.microsoft.com/symbols”
– In “Cache symbols from symbol servers to this directory” enter
• c:\symbols\Public
• The easy way: use .\Scripts\Set-VS2010SymbolServer.ps1
– Part of code disk for this session
The .NET Reference Source Code (cont.)
• Now every time you debug, you’ll download the .NET
Reference Source
• Can be very slow the first time you run on a machine
• May want to consider only loading symbols manually
– So you pay the download tax only when you need to
– Options dialog, Debugging, Symbols
• Uncheck “Search the above locations only when symbols are
loaded manually”
– When you want symbols and source
• Right click on method in Call Stack window and select Load
Symbols
Problems with .NET Reference Source
Downloading
• The debugger can only download a single file at a time
• Would be nice to have the following
– A batch download of all supported files into your cache
– A way to work with proxy servers
– A way to even have .NET source debugging with VS 2005 or
CodeGear tools
• NetMassDownloader to the rescue
– http://www.codeplex.com/NetMassDownloader
– By Kerem Kusmezer and John Robbins
– To download all the current sources from Microsoft:
netmassdownloader
-d "C:\Program Files\Reference Assemblies\Microsoft\Framework\v4.0"
-d C:\windows\Microsoft.NET\Framework\v4.0.30128
Debugging Exceptions
• A little used, but powerful feature of the debugger is the
Exceptions dialog
• Checking thrown will stop on the throw statement
Exceptions Handled by the Debugger
• C++ Exceptions
– Native code language exceptions
• Common Language Runtime Exceptions
– Managed exceptions from .NET applications
– Every FCL exception is listed by default
• Managed Debugging Assistants
– Diagnostic error notifications from the CLR
• Native Run-Time Checks
– The outstanding native /RTC switch exceptions
• Win32 Exceptions
– The well known Win32 native exceptions
The Debugging Tricks with Exceptions
• In many cases, you want to stop when the exception is
thrown so you can start debugging right from the moment
a problem happens
• The steps
– Select the exception in the Exception dialog
– Check the throw box next to the particular exception
• Great idea to set the entire CLR Exception tree to “Break
into the Debugger”
– This lets you see how many exceptions are being thrown
– Helps you determine performance issues with exceptions
Adding Your Own Exceptions
• If you want your custom exceptions in the Exception dialog
– Click the Add button
– Select Common Language Runtime Exceptions in the Type combo
box
– Type in the completely qualified name of your custom exception in
the New Common Language Runtime Exceptions dialog
– Data is saved to the .SUO file for the project
Mini Dumps with VS
• Get in the habit of saving dumps when debugging
– Debug, Save Dump As command
• Open dumps with File, Open menu
– Initiate analysis by clicking on “Debug with Mixed”
• Saves you tons of time!
– No longer have to open all dumps with WinDBG+SOS
• Hints
– Make sure Symbol Server is set up
– For private build binaries and PDB files
• Put them in same directory as .DMP file
– Only works for .NET 4.0 applications
IntelliTrace: Why VS 2010 ROCKS!
• Stopping in the debugger is just a “moment in time”
– Like looking at a photograph
• A video of everything that happened up to the current point
would be even better
– That’s exactly what IntelliTrace is all about
• The most exciting advance in debugging in 20 years
• You’ll easily debug problems 25% faster with IntelliTrace
• Caveats
– Only in Visual Studio 2010 Ultimate
– Today only works with x86 binaries in the debugger
• IntelliTrace integrated into Microsoft Test Manager (MTM) and
works with x64
Initially Setting up IntelliTrace
• Key to IntelliTrace
– RECORD EVERYTHING!
• IntelliTrace General Page
– Enable IntelliTrace events and call information
Initially Setting up IntelliTrace (cont.)
• IntelliTrace, IntelliTrace Events Page
– Enable all events
– Seriously!
IntelliTrace Usage Hints
• Turn off VSHOST for WPF, Win Forms & console apps
– Makes it easier to find your code
• Finding an executed line or method is hidden in the UI
– Right click on line
– Select “Search for This Line/Method in IntelliTrace”
– Use Information Bar at top of source window to find the exact
execution
IntelliTrace Usage Oddness
• So you finish debugging and want to look at the last run
log
– POOF! The IntelliTrace log disappears as soon as you stop
debugging
• Use the Wintellect macro:
IntelliTraceHelper/OpenLastIntelliTraceRecording
– Opens the last recorded log
– Double click one of the threads to load the log
Remote Debugging
• Remote debugging has gotten even easier with Visual
Studio
–
–
–
–
No longer requires an installation process; now either
XCOPY the required bits
Share the directory with the bits and run
Supports cross CPU debugging
• Bits are in <Install Path>Common7\IDE\Remote
Debugger\<CPU>
– Where CPU is x86, x64, or ia64
Remote Machine Initial Setup
• On the remote machines run MSVSMON.EXE to get the
firewall configured
– Must be an administrator on the machine to unblock ports
• Leave the defaults in place
• Look at the first line in the MSVSMON.EXE UI and record
the default name of the server
• Optionally, set any permissions using the Options dialog
Local Machine Initial Setup
• Select the Tools, Attach to Process menu
• In the Qualifier field, type in the server name of the remote
machine
• Click the Refresh button
– When prompted with updating the firewall, select the appropriate
level and click OK
• You still may not connect as the administrator account may not
have permissions on the other machine
• Start Visual Studio with the same account you logged into
the remote machine with
– Go through the attach process and you’ll connect
Using MSVSMON.EXE as a Service
• The default usage model requires you to be logged into the
remote machine for debugging to work
• Install the Remote Debugging Components from Visual
Studio CD/DVD
– <Drive>:\Remote Debugger\<cpu>\RDBGSETUP.EXE
• If Visual Studio is installed on the machine
– Run <VS DIR>\Common7\IDE\RDBGWIZ.EXE
• For domain-based systems, use LocalService as account
• For workgroups, use an Administrator account for service
• Only accounts in Administrator group can connect and
debug
Setting Up a Project
• In the project Property Pages, Debug page
– Check Use remote debugging
– Specify the remote machine connection string
– If the binary is in the same location on both machines
• You do not need to do anything else
– If the binary is in a different location on the remote machine
• Select the Start external program radio button
• In the edit box, type in the complete drive, path, and filename
to the EXE just like you were typing it on the remote machine
Where Do the PDB Files Go?
• Ideally in a symbol server
• For native debugging, symbols are loaded on the local
machine
– Where the IDE is running
• For managed debugging, symbols are loaded on the
remote machine
– Remote debugging includes SYMSRV.DLL so set up the
_NT_SYMBOL_PATH environment variable on the remote machine
• If not using a symbol server
– Put the PDB files in the same directories as the binaries on both
machines
• Source files are found using paths on the local machine
Remote Debugging Troubleshooting
• “Access denied” errors in workgroups
– Check the security options
• Start Local Security Settings MMC
• Go to Local Policies/Security Options
• Make sure “Network Access: Sharing and security model for
local accounts” is set to Classic
Questions?
john@wintellect.com
Download