The opinions expressed in these materials are my own and are not necessarily those of Microsoft.
Copyright © Microsoft Corporation. All rights reserved. Unless otherwise indicated, all source code provided is licensed under the Microsoft Public License (Ms-PL).
This is a multi-part series, you can find the other parts here:
Understanding IntelliTrace Part I: What the @#$% is IntelliTrace?
Understanding IntelliTrace Part II: Where Do I Use IntelliTrace?
Understanding IntelliTrace Part III: IntelliTrace Events
Understanding IntelliTrace Part IV: IntelliTrace Calls
Before we get started I want to be absolutely clear: there is nothing “advanced” about the setting we are going to talk about. The word “advanced” in this case could (and probably should) be replaced with “miscellaneous” or, better yet, “stuff you should always have turned on”. I am, of course, talking about the setting found at Tools | Options | IntelliTrace | Advanced:
We will go though each of these in order and make sure you are clear on reasons for usage. Remember we are using the Brian Keller Virtual Machine with the Tailspin Toys sample code for these posts although this specific post can be used with any codebase.
Running IntelliTrace sessions is great but the experience ends when you stop debugging. Try it and see what I mean. Get some IntelliTrace info up doing one of the exercises in the previous post:
Now stop debugging. Notice the IntelliTrace window completely goes away and there is no way to bring it back UNLESS you start a new debugging session or record an IntelliTrace log file. How do we get a log file? Just go to | Options | IntelliTrace | Advanced and select Store IntelliTrace Recordings In This Directory:
You might also want to create a new local directory with a shorter path to hold your logs:
Now you have a place for your IntelliTrace sessions to be stored:
We will dig into the specifics of what the log files contain in a later post however feel free to open one of these up and poke around on your own if you want.
The next decision to make is our log file size. I suggest a minimum of 500MB to 1GB regardless of activity. If in doubt then go with No Size Limit but watch the file closely. Choose your size carefully. Here are the criteria you need to consider when choosing log file size:
The log files are cyclic which means that when it fills up it will begin overwriting the oldest entries in favor of newer ones.
Are you collecting Events Only or Events and Calls? Events Only consumes much less space so you can go with smaller log sizes if needed. Events and Calls will require significantly more space so plan accordingly.
The size of your log file determines, in essence, your time window. Capturing 500MB will capture half the time window that 1GB will. Since the log files are cyclic they will only capture a sliding time window until the trace stops.
We will explore navigation more in another post but, for now, leave this setting selected:
This will give you special navigation features that are useful when troubleshooting IntelliTrace Calls:
Turning it off simply removes the navigation buttons and the gutter:
Selecting the Enable Team Foundation Server Symbol Path Lookup option will enable the system so that when you are using IntelliTrace or an IntelliTrace log file it can use the build information to automatically try and pull down the matching symbol information for the build you are debugging. This option assumes you have a TFS Build server set up.
Selecting the Prompt To Enable Source Server Support option actually will give you a dialog that will automatically turn on another option found at Tools | Options | Debugging | General | Enable Source Server Support:
To clarify what this means I’ll point you to the documentation on this option and what it says:
Tells the Visual Studio debugger to get source files from source servers that implement the SrcSrv (srcsrv.dll) protocol. Team Foundation Server and and the Debugging Tools for Windows are two source servers that implement the protocol.
To expand on this we can go to another source for more information:
When there is no source code on the local machine or the PDB file does not match the source code, you can use Source Server to help debug an application. Source Server takes requests for files and returns the actual files. Source Server runs by means of a DLL file named srcsrv.dll. Source Server reads the application's PDB file, which contains pointers to the source code repository, as well as commands used to retrieve source code from the repository.
This area of IntelliTrace is fairly easy to wrap you head around in terms of decision-making: turn everything on. The only real question is what size your log file needs to be. As I teach you more advanced techniques just make sure you don’t fill up your drive with an unattended IntelliTrace session that is being logged.
Continuing with our examination of how to use IntelliTrace this post will focus on another set of skills needed for troubleshooting when events aren’t enough. We use events for errors that are surfaced through the events we have specified. In the last post we looked at a classic 404 error and how to troubleshoot using IntelliTrace.
What if the error is more subtle or even intermittent? What if we need more information than events alone can give us? For more detailed information we turn to IntelliTrace Calls. Now is a good time to review the previous post if you haven’t read it yet or haven’t seen the information in a while. Whereas events are quick, low-overhead inflection points we can put into the code; calls incur a lot of overhead but you get a LOT of information.
Here is how the documentation describes IntelliTrace call information:
You can configure IntelliTrace to collect call information for functions. This information lets you see a history of the call stack and lets you step backward and forward through calls in the code. For each function call, IntelliTrace records this data:
Values of primitive data types passed as parameters at function entry points and returned at function exit points
Values of automatic properties when they are read or changed
Pointers to first-level child objects, but not their values other than if they were null or not
NOTE: IntelliTrace collects only the first 256 objects in arrays and the first 256 characters for strings.
The best way to learn about calls is to go through a scenario. Let’s get started by setting up IntelliTrace to collect call information. We will be using the Brian Keller Virtual Machine with the Tailspin Toys codebase just like when we learned about events. Open the Tailspin Toys solution then go to Tools | Options | IntelliTrace | General and turn on IntelliTrace Events and Call Information:
Take note of the warning. You will not be able to use Edit and Continue while using Call Information so you will have to stop debugging to correct issues when you find them. It’s not a huge issue but something you need to be aware of as you use this feature so the team decided to call it out on this dialog.
One of the most confusing aspects of IntelliTrace is filtering the calls. Remember that we can use the IntelliTrace Events area to filter event information but there doesn’t seem to be an obvious place to filter call information. Where could it possibly be? In the IntelliTrace world we filter calls by filtering out the processes and modules that the calls come from/to. As we will see in a later post, there are places where we can’t assume the process and therefore have to specify a list of processes to capture. An example of this can be found in Microsoft Test Manager when we configure IntelliTrace:
Because we are in Visual Studio, however, there is no need for us to figure out the process since we assume the current process when we start a debugging session. The only thing we worry about is module filtering which can be found at Tools | Options | IntelliTrace | Modules:
Regardless of the type of call filtering you are doing there is one fundamental choice that needs to be made: deciding to include or exclude items. The default behavior, seen in the above process and module screenshots, is to use a blacklist of items to EXCLUDE from collection. The danger of doing this is you will collect everything unless you specifically tell IntelliTrace not to collect. If you recall from my previous lesson on filtering events my personal feeling is that you should collect as much as you can and then filter AFTER the data is gathered. This will cause performance loss during collection but will give you the most information to work with.
The other option is to use a whitelist of items to INCLUDE during collection. The danger here is you might miss an important piece of information that was not included. From a performance perspective this is the best way to get a performance boost because IntelliTrace doesn’t have to collect as much information. As before there is no “right” answer to this situation--just personal preference.
Even though you can’t change it from Visual Studio, there actually IS a list of processes to be excluded. In time I’ll show you how to modify the entries but, for now, here is the list of processes currently excluded when you use IntelliTrace from Visual Studio:
(NOTE: Feel free to Bing any of the processes you are not familiar with.)
The modules filtered by default are essentially any assemblies we provide. You can quickly get an idea of which assemblies are excluded by going to the GAC (<windows install dir>\assembly) and comparing the list of exclusions to entries there. Here is the list of modules excluded by default in Visual Studio:
The main goal of the default filters is to keep the noise from Microsoft products to a minimum. As you can see by the list of processes and modules the default filters center around specific processes and modules that we expect you are least likely to want in result sets. You can add or remove items from the list as needed to get the desired level of detail. For our scenario we will use the default call filtering settings.
Build and run the Tailspin Toys sample code. We are going to experience a problem that can’t be solved with events. First, let’s buy some airplanes! Okay, paper airplanes but still pretty cool stuff. Select Paper Airplanes:
There are lot of good choices here but, for now, view the Contoso Cloud Explorer:
Add one of these to your cart and notice the number of items in the cart goes up by one:
Select the Contoso Cloud Explorer link to view the details again:
Add another one to your cart and notice the number of items is still one:
Clearly we have a logic error in the code. Events won’t help us much here because there is no exception raised or other event that will lead us to the problem. Also, we know we are going to have to dig deeper into the code for answers. This scenario literally screams for you to collect call information. Switch back to Visual Studio and let’s examine the IntelliTrace data by breaking execution:
We know that the problem surfaced after the second time we tried to add an item to our cart so filtering on ASP.NET events seems like a good starting point:
(NOTE: Unfortunately event filtering in the IntelliTrace window is still a bit of a blunt instrument. You can filter on event categories but not on specific types of events.)
Once we have the filtered data we can scan for the interesting event or filter further by searching for keywords. Since we know the issue is related to our shopping cart we should probably try searching for the word “cart”:
The resulting list is very easy to scan and we can find a starting point for our troubleshooting efforts. In this case, the second AddItem POST is the perfect anchor point for our searching:
The events only tell us that we sent some data to the server now we need to get into the code. Click the Calls View link:
Notice that our anchor point is highlighted and we are now in the Calls View window:
This window can be a little confusing at first so taking a closer look at this point is a good idea. First, the window is divided into two pieces. The top piece (above the double lines) is the current call in our history:
The second piece is indented below the double lines and represents calls from the current call and events associated with the current call:
As we look at our current location we know that the issue we are looking for happened after the POST. As we look down the timeline of calls there is definitely one that stands out--the AddItem call:
If you double-click this call it will become our current call and we can see more information:
At this point we are in our code so we can see our current location not only in the tool window but also in the code base:
Notice there is another call to AddItem below our function entry point. Click once on the entry and we can examine the code:
It looks like another call to AddItem and apparently we are building up information as we make these calls. Notice it is passing in product information for this particular call. If we double-click here then we get another set of calls with yet another AddItem:
Notice how we are building up our call stack above the double lines? As we keep drilling down we get clear line-of-sight to the call path we are going down. Drill down (double click) on the next AddItem call and pay attend to the code to the left as we keep searching for where the quantity is updated:
Drill down again. Notice we have run out of AddItem calls but we might have finally found our culprit with the AdjustQuantity call:
A look at the code shows that we are probably on the right track:
Let’s take a look at the Locals window to get more information about this call:
We can definitely see a potential problem with newQuantity. At this point we could continue to dig into AdjustQuantity but, for now, we will assume we know this is the area to be fixed. The problem is we are passing the quantity of the current item but we are not adding it to the existing quantity. It’s a simple fix, we just stop debugging and modify the code as follows:
Build and run the code. Make sure the fix worked by adding some planes to your cart. You should see the quantity going up as you add items to it:
In this post the goal was to teach you about IntelliTrace calls and do an introduction to troubleshooting with the feature. The ability to browse a historical call stack and view the associated code raises problem resolution to a new level. There are a few limitations but, for the most part, you can debug historical code just like any normal debugging session. Later on we will explore more on how to do more advanced navigation in the editor and other advanced topics.
Okay campers we have covered the “what” and “where” so the remaining posts will deal with the “how” of IntelliTrace. There are some fundamental pieces to the technology that we will look at and then explore specific scenarios for utilization. So let’s get started!
The first thing you will need to know is the exact types of applications you can use with IntelliTrace. Here is information straight from the documentation (http://msdn.microsoft.com/en-us/library/dd264915(v=vs.110).aspx#IntelliTraceSupport):
Visual Basic and Visual C# apps that use the .NET Framework 2.0, 3.0, 3.5, 4.0, or 4.5.
You can debug most applications, including ASP.NET, Windows Azure, Windows Forms, WCF, WPF, Windows Workflow, SharePoint 2010, and 64-bit apps. To debug SharePoint 2010 applications with IntelliTrace, see Walkthrough: Debugging a SharePoint Application by Using IntelliTrace. To debug Windows Azure apps with IntelliTrace, see Debugging a Published Cloud Service with IntelliTrace and Visual Studio.
F# apps on an experimental basis
Windows Store apps supported for events only
C++, other languages, and script
Silverlight, Xbox, or Windows Mobile apps
NOTE: If you want to debug a process that is already running, you can’t use IntelliTrace. You must start IntelliTrace when the process starts. We will look at why this is the case down the road.
The first thing you have to know is how to turn IntelliTrace on. If you are using Visual Studio 2012 then this feature is already turned on but if you are using Visual Studio 2010 then you will need to turn it on. Either way it’s always a good idea to make sure it is turned on, just in case. Go to Tools | Options | IntelliTrace | General and select Enable IntelliTrace:
Notice you have two choices when you turn it on. For now we will go with the default, IntelliTrace Events Only. In the next post we will explore call information.
So what are these events that we have? Well, in a general sense, they are low-impact, high-value inflection points in the codebase that we use to quickly pinpoint issues. IntelliTrace comes with several pre-defined events and you can even add custom events. For now we will explore the pre-defined events. You can see the current list of events we supply by going to Tools | Options | IntelliTrace | IntelliTrace Events:
Notice there are sets of broad categories. Expand the ASP.NET node and notice we can further drill down into the details if we only want to capture certain events. Take some time now to look over the categories and events in each category:
You can decide which events you want to capture from this dialog however there are two schools of thought on how to use this area:
One school of thought suggests you use this dialog to pre-filter out events you think you don’t need. The upside to this is improved performance when using IntelliTrace since a lot of information doesn’t have to be gathered. The downside is you could miss something that didn’t show up because you filtered it out. This theory is supported by the IntelliTrace team (run by my friend Larry Guger) and is the main reason this dialog exists in the first place.
The other school of thought says you should collect everything you can now and filter out information later. The upside is you can look at all the data and catch more issues. The downside is you take a larger performance hit when using IntelliTrace. This is the theory I adhere to along with my friend and BBQ buddy John Robbins.
Choosing Your Filter Strategy
Neither of the theories are “right” they are just personal choices we have made. If you find the performance hit is too much for you then go with pre-filtering to get a perf bump. Otherwise, I strongly suggest you try the “filter later” approach at least until you get a sense of what should be filtered out.
Now that we have covered the basics let’s actually use IntelliTrace! All the demos I’m doing are based on Brain Keller’s Visual Studio 2012 Virtual Machine and you should absolutely use this VM if you can to practice your skills. Also, grab my IntelliTrace Everywhere Deep Dive material while you are at it to do these examples on your own. The great thing about using a virtual machine is the ability to rollback to a prior snapshot so you can always go back to a “clean” environment if you need to.
Make sure you have IntelliTrace Events Only turned on and, for this demo, all pre-defined events are being collected as well:
I’m using the Tailspin Toys codebase for these examples but you can substitute it with any MVC example web app. The scenario we are going to troubleshoot is a classic 404 error. In Visual Studio 2012, build and run the Tailspin Toys example:
(NOTE: You will notice a performance hit when loading for the first time. I will explain why this happens later.)
Select the About Us link in the lower left-hand corner and notice we get a (somewhat handled) 404 error:
We realize we have a problem. Switch over to Visual Studio and notice the IntelliTrace window (Debug | Windows | IntelliTrace Events):
Select Break All to start a debugging session and give us our historical data in the IntelliTrace Events window:
What are we looking at here? The first thing you need to realize is that you are looking at the history of events up until we entered the debugger. The most recent activity is at the bottom and, scrolling up, we see things that occurred further in the past. Notice that we are currently in live debugging mode and can do all the normal activities we would engage in as if there were no IntelliTrace. If another item further back in the list is selected we can see some historical information:
(NOTE: If you don’t have Update 1 installed for Visual Studio then you will not see the time stamp but otherwise everything else should look the same.)
One of the keys to success with using IntelliTrace is knowing how to leverage what I call “anchor points”. That’s not an official name but it’s the best descriptor, I believe, for the concept. Recall we had a problem with the About page. It seems natural to look for any entries that reference this page. Notice we have a search area for this tool window:
Look for any entries that contain the word “about” in them:
There are a lot of entries but clearly our problem started sometime after the GET request for the about page. Select this item in the list to create our anchor point:
Now we can clear the search:
Now we have an unfiltered history with our anchor point:
We can safely assume that anything interesting to us will happen after the GET request so we scroll down to see things that happened AFTER that specific point in time:
The first exceptions we come across appear to be what we are looking for at first glance:
Take a closer look. There is a series of these errors and the paths change from /Views/Home to /Views/Shared and different extensions are tried (.aspx and .ascx):
These are your first examples of “noise” in the results. The errors are typical ones you see in MVC applications and are related to routing. In any given type of application you are working with you will encounter some type of noise in the result sets. Be aware of them and, over time, you will learn the specific types of noise for your situation.
As we continue to examine the timeline we see our next exception occurs after we tried to load an XML document:
As you can see in this case the error is pretty specific. It gives us the line and position of where it thinks the error to be. If we look at the File Access event there is a link to the offending XML file:
Clicking the link opens the file and if we go to the line and position specified we can clearly see the error:
When we go to edit the file this dialog is what we are presented with:
Click the Edit button and we can fix the problem:
Restart the debugging session and you should find the problem is fixed:
Here is a slide I created when explaining how IntelliTrace works:
Let’s walk through what’s happening. When you build your source the result, of course, is an assembly with Microsoft Intermediate Language (MSIL) code in it. At the time the assembly is used (“run”) the MSIL code is Just in Time (JIT) compiled into machine language. IntelliTrace injects code (using the CLR Profiler) when the assembly is JIT compiled so the information required can be gathered. The more information you need the more IntelliTrace code that has to be injected which is why you always take an up-front performance hit when using it but the application becomes more responsive after the assembly is loaded. This is also the reason why IntelliTrace needs to catch the application as it is loading.
I always hate the end of these things because I always feel like I haven’t said enough. The good news is there will be many more posts to clarify and enhance your IntelliTrace education. In this post the goal was to teach you about IntelliTrace events and do an introduction to troubleshooting with the feature. Resolving issues with the historical information will reduce resolution time. Be aware that there is always noise in every IntelliTrace capture and you will learn to identify those patterns in your codebase. Resolving issues with events is the first part of the IntelliTrace education. In the next post we will explore how to work with calls.
ASP.NET and Web Tools 2012.2 is a tooling refresh of Visual Studio 2012 that extends the existing ASP.NET runtime with new features without breaking existing applications. ASP.NET and Web Tools 2012.2 installs in minutes without altering the current ASP.NET run time components. Click the green button to download and install right now. For a complete description see the Release Notes or watch the video. This .2 update adds a number of new templates and features including:
Download ASP.NET and Web Tools 2012.2 Today!
From the Release Notes at http://www.asp.net/vnext/overview/fall-2012-update/aspnet-and-web-tools-20122-release-notes-rtw
This section describes features that have been introduced in the ASP.NET and Web Tools 2012.2 release.
ASP.NET Web API has been enhanced with several new features:
ASP.NET Web API OData
ASP.NET Web API OData gives you the flexibility you need to build OData endpoints with rich business logic over any data source. With ASP.NET Web API OData you control the amount of OData semantics that you want to expose. ASP.NET Web API OData is included with the ASP.NET MVC 4 project templates and is also available from NuGet (http://www.nuget.org/packages/microsoft.aspnet.webapi.odata).
ASP.NET Web API OData currently supports the following features:
For more information on ASP.NET Web API OData see http://go.microsoft.com/fwlink/?LinkId=271141.
ASP.NET Web API Tracing
ASP.NET Web API Tracing integrates tracing data from your web APIs with .NET Tracing. It is now enabled by default in the Web API project template. Tracing data for your web APIs is sent to the Output window and is made available through IntelliTrace. ASP.NET Web API Tracing enables you to trace information about your Web API when hosted on Windows Azure through integration with Windows Azure Diagnostics. You can also install and enable ASP.NET Web API Tracing in any application using the ASP.NET Web API Tracing NuGet package (http://www.nuget.org/packages/microsoft.aspnet.webapi.tracing).
For more information on configuring and using ASP.NET Web API Tracing see http://go.microsoft.com/fwlink/?LinkID=269874.
ASP.NET Web API Help Page
The ASP.NET Web API Help Page is now included by default in the Web API project template. The ASP.NET Web API Help Page automatically generates documentation for web APIs including the HTTP endpoints, the supported HTTP methods, parameters and example request and response message payloads. Documentation is automatically pulled from comments in your code. You can also add the ASP.NET Web API Help Page to any application using the ASP.NET Web API Help Page NuGet package (http://www.nuget.org/packages/microsoft.aspnet.webapi.helppage).
For more information on setting up and customizing the ASP.NET Web API Help Page see http://go.microsoft.com/fwlink/?LinkId=271140.
ASP.NET SignalR makes it simple to add real-time web capabilities to your ASP.NET application, using WebSockets if available and automatically falling back to other techniques when it isn’t.
For more information on using ASP.NET SignalR see http://go.microsoft.com/fwlink/?LinkId=271271.
ASP.NET FriendlyURLs makes it very easy for web forms developers to generate cleaner looking URLs(without the .aspx extension). It requires little to no configuration and can be used with existing ASP.NET v4.0 applications. The FriendlyURLs feature also makes it easier for developers to add mobile support to their applications, by supporting switching between desktop and mobile views.
For more information on installing and using ASP.NET Friendly URLs see http://www.hanselman.com/blog/IntroducingASPNETFriendlyUrlsCleanerURLsEasierRoutingAndMobileViewsForASPNETWebForms
In the last post I talked about the concept of what IntelliTrace is used for. In this article I thought it would be a good idea to visit where you would want to use this feature. I’m really trying to knock out another set of misconceptions here. On those occasions when people are shown IntelliTrace they tend to see it in one place while never realizing that is can be used almost everywhere. It’s part of the reason I entitled my workshop materials “IntelliTrace Everywhere Deep Dive.” (http://sdrv.ms/UPUEE3) I want to preface everything you are about to see with the following: We will be looking at each of these items in turn with future posts. The point, right now, is to make sure you know where this stuff can be used and, hopefully, get excited about a scenario that applies to you.
The most obvious place you will find yourself using IntelliTrace is inside the IDE. During any debugging session you can easily jump into the IntelliTrace window and go through the history:
Ironically, the first time most people see IntelliTrace is when we show it with Microsoft Test Manager. Using it to help reduce the amount of back-and-forth that needs to happen before the developer can start working on an issue raised from the testing folks. This is a huge improvement that allows developers to really get to the heart of an issue quickly.
IntelliTrace can be used to troubleshoot ASP.NET applications that are running in production or anywhere else. A special assembly with PowerShell commands. In a later post we will explore the details of how this works:
You can use IntelliTrace on any computer running .NET 2.0 - 4.5 (for the application) and 3.5 (for IntelliTrace to run). You collect logs using the command line:
In System Center 2012 Service Pack 1 (SP1), Operations Manager has the ability to capture historical snapshots (traces) directly from the Operations Manager console and to receive IntelliTrace snapshots from .NET Application Performance Monitoring (APM) exception events. They provide a view into application execution history without needing to access the servers where the problems occurred. I’ll try to demo this with the new Brian Keller VM that has System Center so folks can do it themselves as well. If you want more information on SCOM / IntelliTrace integration you can go here: http://technet.microsoft.com/en-us/library/jj883935.aspx
As it turns out the ONLY way to debug Windows Azure applications in production is with IntelliTrace. For more information you can go here: http://msdn.microsoft.com/en-us/library/windowsazure/ff683671.aspx
Even though you “could” use IntelliTrace with SharePoint applications before, it was pretty difficult to get certain types of information. Beginning with Visual Studio Update 1 you can now use IntelliTrace to debug SharePoint apps with plenty of information. On a related note if you haven’t looked at Update 1 you really should if you are a SharePoint developer as the team has added a ton of great stuff. If you want more information on IntelliTrace with SharePoint right away you can go here: http://blogs.msdn.com/b/visualstudioalm/archive/2012/12/11/debugging-sharepoint-apps-with-intellitrace-in-visual-studio.aspx
We have covered the “what” and the “where” so beginning with the next post we will start in with the “how” of IntelliTrace. Before that happens I would encourage you to go back and find a scenario that appeals to you so you can visualize where you might get the most impact from this feature. I can honestly say the only thing I’m more passionate about than IntelliTrace is Visual Studio. Even then it’s pretty close. IntelliTrace is an incredible tool for developers.
This series is based on my IntelliTrace Workshop materials found here: http://sdrv.ms/UPUEE3
Over the next few posts I’m going to explain IntelliTrace in consumable chunks so folks can get a handle on it. Even though we introduced it in Visual Studio 2010, it’s still one of the more misunderstood features we have in the IDE. Together we will navigate through the what, where, and how of IntelliTrace to, hopefully, come out ready to engage in debugging bliss. :)
Before you can use IntelliTrace you have to understand what it is. There are several good explanations people use to describe how this works. I think the best way to do this is to compare it with live debugging by using an analogy.
NOTE: IntelliTrace can be used for debugging .NET 2.0 - .NET 4.5 assemblies however, you need .NET 3.5 to run IntelliTrace itself so, at a minimum, you need .NET 3.5 and the Framework version you want to debug.
Imagine live debugging as being like directing a cast of people on stage. You can bring different people to the front, you can make them move around, change their look if you want, and so forth. Essentially, you have complete control over what is seen at any point in time BUT you can’t rewind to look at what has happened in the past and you can’t fast-forward. All you can basically do is focus on what is happening right now.
Similarly, you can break execution, step through your code,and even dynamically change variable values for variables in scope. There is a LOT of control but you can’t go back once you have passed a line of code unless you restart the entire debugging session. Therefore, live debugging is very much point-in-time oriented.
Unlike live debugging, IntelliTrace debugging is like watching a video of the stage play. You can fast-forward past the boring parts and rewind if you missed something. The one thing you can’t do is change what is happening since it has already happened in the past. You give up controlling the actors in favor of controlling the timeline. In fact, IntelliTrace was originally called “Historical Debugging” when we introduced it.
I like the title of this section because most people who don’t know about IntelliTrace assume that it replaces live debugging. Let me be perfectly clear: IntelliTrace DOES NOT replace live debugging. Not today, not tomorrow, not ever. In fact, the two were meant to work together. You can see this when you are using IntelliTrace as it always gives you the option to go back to live debugging whenever you want:
It’s common to be in the middle of a live debugging session, then need to use IntelliTrace to see something that happened in the past, and then switch back to live debugging to pick up where you left off.
Okay so I “might” have mislead you into thinking that you would come away from this article completely understanding IntelliTrace but it was all part of my evil plan. You can’t really understand the feature until you use it and that is exactly what we will do in this series. We are going to build up scenarios and and hopefully have you come away with much deeper appreciation of this technology.
With the addition of Visual Studio Update 1 we introduced a cool new feature called Code Map. You can use Code Map to visualize relationships in code. In this article we will explore this new feature and show you how to use it.
Before we get started you need to be aware of the requirements for Code Map. Below are the requirements to leverage this feature:
Visual Studio 2012.1 and one of these editions:
Visual Studio 2012 Ultimate to create code maps from the code editor or from Solution Explorer.
Note: Before you share maps with others who use Premium or Professional, make sure that all the items on the map are visible, such as hidden items, expanded groups, and cross-group links.
Visual Studio 2012 Premium or Visual Studio 2012 Professional to open code maps, make limited edits, and navigate code.
A solution with Visual C# .NET or Visual Basic .NET code
With that said, I often see many larger organizations who usually have a few extra Ultimate licenses so you might ask around at your company to see if there are any available licenses if you need the higher level version.
We will get to examples of maps in a minute but I wanted to help clarify their origin. Code Maps are a more user-friendly approach to something we have had in Ultimate for a while known as Dependency Graphs. With this new feature we make creating and manipulating visualizations easier. I bring this up because you may want to explore creating Dependency Graphs to learn more about how to work with these visualizations. You can find out more here:
The need for maps will usually manifest itself when you are writing or debugging code and need to understand code relationships. Let’s take, for example, TailSpin Toys from the Brian Keller Virtual machine found at:
Let’s say I happen to be looking at the AddItem method and want to get a handle on what is calling this method. I can right-click the method and choose Show on Code Map (note the shortcut key as well):
NOTE: I’m showing this path for demo purposes. As you get more advanced you may want to choose an option from the Show Related Items on Code Map menu:
Once you choose to show an item on the map, Visual Studio will build the solution and index it to generate the initial map image:
The first image may not look like much:
I want to see anything that calls this method. I can go to Show Related Items on the toolbar or simply right-click the AddItem node and choose Find All References:
Now we have a map! We can visualize our method and calls to it:
I’m not a fan of the default orientation (Top to Bottom) in this case so go to the toolbar and select the Left to Right Layout:
Which will give a little better perspective on what is happening:
If you need to fit the diagram to your viewing area you can use the Zoom To Fit button on the Code Map Toolbar:
NOTE: Whenever you add nodes the most recently added ones will be in green. If this annoys you, you can clear the green color by going to to Layout on the Code Map Toolbar and selecting Clear Result Highlighting or by pressing CTRL + G:
You can see the legend by going to the Code Map Toolbar:
You can hover your mouse over any node to get more detail and/or you can double-click any node to see the code associated with it:
Note the green arrow beside the node you are currently viewing. This is just like the map in the mall that says, “You are here.” It is meant to clearly show where in the codebase you are examining. The arrow only shows up on nodes when the editor cursor is in the code underlying them:
You can also flag nodes using a variety of colors to indicate some type of action needs to be taken:
If you need to have more detail, you can add comments to any node by right-clicking the node and selecting New Comment:
At some point you will want to share the Code Map with others. If you want the diagram to travel with source control you can move the diagram to an existing project by going to Share on the Code Map Toolbar and moving the map file to an existing project:
You will see it show up in your project after you move it:
Attaching the diagram to your source code is the optimal option but you can also choose one of the other methods from the Share button on the toolbar as well to share with others.
As you can see there is quite a bit to using Code Map and it is a great way to get a handle on complex code bases. I hope you like this feature as much as I do.
I had a customer accidentally delete some test cases in Team Foundation Server the other day and call me in a panic. Fortunately they had good backups and the story ended well but I thought it would be good to review what is needed in case you accidentally delete your work items.
TFS uses databases and, therefore, the key to recovering in TFS is making sure you are backing up and are able to recover the underlying databases. Here is the guidance on how to do just that:
Not all artifacts are easy to recover. Test Plans are particularly fun to get back so my friend Angela wrote an article about how to recover in those special situations:
Being able to recover means having a good relationship with your database administrator. Make sure you are in sync on the TFS install and what pieces of the deployment are high value vs. low value projects, etc… Like in most things communication is the key to success and there is not such thing as over communicating when it comes to your TFS instance…
…Okay there IS such a thing as over communicating so don’t, for example, hire an airplane to fly over your building with your favorite table name from the TFS database.
Before I begin digging into some of the stuff in Update 1, I thought it would be a good idea to review some of the features I’ve blogged so far on Visual Studio 2012 features. Below is a quick list of the features (in no particular order) with links to the more detailed blog posts.
Technically this isn’t a “feature” but it is by far one of my most popular posts. This article is about how to turn off the annoying uppercase menu bar so you can go from SHOUTING:
To Something Normal:
You can now create projects in Visual Studio 2010 with Service Pack 1 then open those projects in Visual Studio 2012 and THEN open the project up again in VS2010 SP1. This works the other way, too! You can create projects in VS2012 (targeting Framework version 4 or less) then open the project in VS2010 SP1 and THEN open it up in VS2012 again. In other words, we now have project round-tripping capability so you can work with the latest features but still keep the solution compatible with team members using an older version of Visual Studio.
We all explore code and need to move quickly between files when examining code to get familiar with it or debugging or [insert file browsing scenario here]. In prior versions of Visual Studio you had to open a file to look at the contents which often resulted in many open files (tabs) when you were done. The Preview Tab eliminates the need to open files when browsing code. Most likely you’ll first encounter the Preview Tab when you are looking at files with Solution Explorer. When you click on a supported file type, you will see the contents of that file in the new preview tab (to the far right in the tab well).
In the past, finding things deep in the IDE has been a challenge. Visual Studio 2012 introduces search abilities at virtually every level of the product. Perhaps the biggest change is the introduction of Quick Launch (CTRL + Q) which specifically addresses how to dig inside Visual Studio to find features you need.
You can now search items in Solution Explorer, make copies of the Solution Explorer window, and much more! This post is a must-read.
For Visual Studio Premium and Ultimate users there is a great new add-in for PowerPoint that can really help you called the PowerPoint Storyboarding add-in. Using this feature you can quickly draft an interface design and get stakeholder feedback. Plus, since it’s PowerPoint, even stakeholders can change elements easily to show you what they really want.
For better or worse we have all had code that gets copied throughout our solutions. Until now there was no tool to tell us there were copies and, instead, we had to rely on other metrics to hopefully reveal any code smells that lead us to duplicates. Now, however, we have the new Code Clone Detection (aka Code Clone Analysis) feature.
A customer asked me the other day about excluding different files (or directories) based on the type of build happening. Specifically they wanted to exclude some files for Release builds and others for Debug builds.
Here is the general info on how to exclude files from builds:
Within the article you will want to take a look at the Condition attribute which specifically calls out how to exclude based on build type:
Condition=" '$(Configuration)' == 'Release' " />