Errors when adding an assembly reference in Visual Studio
My work machine has finally been upgraded from Windows XP to Windows 7 with a clean installation. And this means reinstalling some tools, taking some time to reorganize and optimize directory structures, etc...
Now I was working on an article (my first deadline!) when I got the following error:

Could not add a reference
The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)
I'm using a custom Add Reference window from the Productivity Power Tools. Maybe it was a bug in the current release of this great extension? After disabling the extension I did get rid of the error but an other one showed up:

Microsoft Visual Studio
The system cannot find the file specified
Hmmz... was my Visual Studio installation broken? One of the other extensions I'm using is: PowerCommands for Visual Studio 2010. This extension has a copy/paste functionality for references, so maybe I could just copy the reference for now and finally start working...

Microsoft Visual Studio
Error HRESULT E_FAIL has been returned from a call to a COM component.
Strange, because only a few hours ago I was working on the same project (on my workstation) and everything worked correctly. The only thing that had changed was the directory structure. And indeed, the culprit was the comma in the directory name.

It seems that you cannot add a reference to an assembly located in a directory containing a comma in its name. Maybe because it could conflict with the commas in the fully qualified assembly name?
Mystery solved! To the Bat Cave, Robin!
Enjoy
A guide to cleaner XAML with custom namespaces and prefixes (WPF/Silverlight)
Introduction
When working with any type of application it's a good idea to split up your solution in multiple projects (assemblies) and namespaces. As your project grows you'll see your amount of namespaces grow with it. And if you plan to use classes / controls from these namespaces in your XAML code, you'll have to declare them with the following syntax:
xmlns:PREFIX="clr-namespace:NAMESPACE"
An example could be:
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
If you are referencing an other assembly, you'll also need to add the assembly name:
xmlns:PREFIX="clr-namespace:NAMESPACE;assembly=ASSEMBLYNAME"
For example:
xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters
;assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
Some namespaces are added by default when you add a new XAML control in your project (be it a UserControl or a Page).
This is how it should look like:
<UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
But, as stated before, when your project starts growing and you need to work with different namespaces and assemblies your references might start piling up and your XAML code gets bloated.
Real Life Example
In the code you'll find the following projects:
These projects reflect how a real application could look like. All controls are organised in a separate namespace Controls (could even be an other assembly) and the same thing applies to the Converters. Then you could have an other assembly with more converters. Maybe this assembly contains some global converters that are used throughout all the projects in your company.
Looking at the XAML of MainPage you'll notice the following:
<UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:Sandworks.Silverlight.NamespaceExample.Controls"
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters;assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
For this small project I already have 3 declarations. Imagine 5 more assemblies, and 20 UserControls making use of all these assemblies. You'll end up copy/pasting, duplicating code, …
But what are are options to clean up our XAML?
Option 1: Custom namespaces
In the example project I added a Calendar (not a default control) to the MainPage. You'll see that Visual Studio will add a reference to System.Windows.Controls and will also add the following to your MainPage:
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
Notice the following:
- Instead of adding "my" or any other word as prefix it added sdk. It would be nice if we can trigger this behavior when adding our controls.
- Instead of a clr-namespace + assembly reference it adds a regular (schema) url.
To achieve this behavior you need to follow the next steps:
- Go to the project where you want to map CLR namespaces to a custom namespace.
- Open AssemblyInfo.cs under Properties
- Add the following to the top of your code: using System.Windows.Markup;
- Add the XmlnsPrefix and XmlnsDefinition attributes.
Example:
[assembly: XmlnsPrefix("http://schemas.sandworks.com/sl/", "sw")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/",
"Sandworks.Silverlight.NoNamespaceExample.Controls")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/",
"Sandworks.Silverlight.NoNamespaceExample.Converters")]
As you can see, we use the XmlnsDefinition attribute to map multiple CLR namespaces to a single custom namespace. The beauty of this is that you aren't limited to a single assembly. In the downloadable source code you'll see these definitions for both the application as for the class library. You could think of organising all your controls, converters, utils, … under a project wide namespace.
So, before we had this:
xmlns:my="clr-namespace:Sandworks.Silverlight.NamespaceExample.Controls"
xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters;
assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary"
And now we have this:
xmlns:sw="http://schemas.sandworks.com/sl/"
Again, imagine 5 more assemblies, and 20 UserControls making use of all these assemblies. No bloating!
If you're referencing 1 or 500 assemblies, you'll just be using this single custom namespace.
Oh, and if you didn't notice yet, the XmlnsPrefix declares the default prefix (for that namespace) that should be added automatically. When I added the Calendar we automatically got an sdk prefix, and now for my own controls I'll automatically have the sw prefix.
Option 2: No namespaces
Now you don't have to stop at Option 1. You could actually get rid of all your extra namespaces. As stated before you are not limited to a single assembly. Meaning more than one assembly can declare the same namespace.
If you take a look at a default UserControl you'll always see this line:
<UserControl x:Class="Sandworks.Silverlight.NoNamespaceExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Well, now you could map all your CLR namespace to this custom namespace, as follows:
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",
"Sandworks.Silverlight.NoNamespaceExample.Controls")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation",
"Sandworks.Silverlight.NoNamespaceExample.Converters")]
Now you achieved 2 things:
- You do not need to add extra namespace references in your XAML controls.
- You get rid of prefixes. Since the presentation namespace is declared without prefix, all your controls, converters, … are accessible without prefix. And this is great for using Intellisense:

I myself prefer Option 1. Totally removing namespaces and prefixes could also become a problem in larger projects. The thing I tend to do is create 1 custom namespace for company wide assemblies and 1 custom namespace for project specific assemblies/projects.
Download
The source contains 2 scenarios. One with regular namespace usage and one with our custom namespaces.
Download here: Sandworks.Silverlight.NamespaceExample.zip (90.74 kb)
More information on this topic can be found here: http://msdn.microsoft.com/en-us/library/cc189061(VS.95).aspx
Enjoy..
Controlling and viewing the ScrollBar positions of your Silverlight DataGrid
Introduction
If you take a look at the Silverlight DataGrid you'll see that you can't control scrolling by default. This could be a hurdle if you're working with data driven applications. What if you want to preserve the scroll position after you reload the DataGrid?
In this article we're going to do 2 things in regard to scrolling:
- Create extension methods to control the DataGrid scrolling.
- Create a custom DataGrid for advanced scenarios.
Scrollbars on the DataGrid
Before we get started here is a quick overview of the DataGrid with scrollbars. Each DataGrid could have up to 2 scrollbars (1 horizontal and 1 vertical). And the button you can drag around is called a thumb (from System.Windows.Controls.Primitives.Thumb).

Creating the DataGridScrollExtensions class
The class we'll create should provide the following functionalities:
- Give us access to both the horizontal and vertical scrollbars
- Inform us about the position (and changes) of the scrollbar thumbs
- Move the scrollbar thumbs
This is how the class looks like:

Finding the Scrollbars
The first thing to do is make sure we can access the scrollbars. This is where we'll use the recursive method GetScrollbars. Using the VisualTreeHelper we can drill down through a DependencyObject (in our case the DataGrid) until we find the Scrollbar. The names you can use to find the right scrollbars are VerticalScrollbar and HorizontalScrollbar (case sensitive!).
private static ScrollBar GetScrollbar(this DependencyObject dep, string name)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dep); i++)
{
var child = VisualTreeHelper.GetChild(dep, i);
if (child != null && child is ScrollBar && ((ScrollBar)child).Name == name)
return child as ScrollBar;
else
{
ScrollBar sub = GetScrollbar(child, name);
if (sub != null)
return sub;
}
}
return null;
}
Now that we have access to the scrollbars we can get to all the information we need. You'll probably want to look at the Maximum and Value properties and also the Scroll event.
Moving the Scrollbars
Moving the scrollbars around is a little trickier. I bet you're thinking the same as I was thinking. Just change the Value property of a scrollbar. Well, I suggest you try that. You'll see that the Thumb will move to the new value of the scrollbar, but the data won't follow. Let's take a look at the DataGrid using Reflector:
public override void OnApplyTemplate()
{
...
this._hScrollBar = base.GetTemplateChild("HorizontalScrollbar") as ScrollBar;
if (this._hScrollBar != null)
{
this._hScrollBar.IsTabStop = false;
this._hScrollBar.Maximum = 0.0;
this._hScrollBar.Orientation = Orientation.Horizontal;
this._hScrollBar.Visibility = Visibility.Collapsed;
this._hScrollBar.Scroll += new ScrollEventHandler(this.HorizontalScrollBar_Scroll);
}
...
this._vScrollBar = base.GetTemplateChild("VerticalScrollbar") as ScrollBar;
if (this._vScrollBar != null)
{
this._vScrollBar.IsTabStop = false;
this._vScrollBar.Maximum = 0.0;
this._vScrollBar.Orientation = Orientation.Vertical;
this._vScrollBar.Visibility = Visibility.Collapsed;
this._vScrollBar.Scroll += new ScrollEventHandler(this.VerticalScrollBar_Scroll);
}
...
}
As you can see the DataGrid subscribes to each ScrollBar's Scroll event. When this event is raised the DataGrid will move the data around. But if you just change the Value of a ScrollBar, the Scroll event won't be triggered.
We'll need to simulate a user moving the ScrollBar around. And maybe you know this, but Silverlight (and .NET) provide a concept that was made for what we're trying to achieve, Microsoft UI Automation. One of its features is simulating user interaction. You can read more about it here and here. The following code gets the AutomationPeer for the DataGrid and this object can provide us with the IScrollProvider.
private static IScrollProvider GetScrollProvider(DataGrid grid)
{
var p = FrameworkElementAutomationPeer.FromElement(grid)
?? FrameworkElementAutomationPeer.CreatePeerForElement(grid);
return p.GetPattern(PatternInterface.Scroll) as IScrollProvider;
}
Finally, using this IScrollProvider you can simulate a scroll interaction:
switch (mode)
{
case ScrollMode.Vertical:
scrollProvider.SetScrollPercent(
System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, percent);
break;
case ScrollMode.Horizontal:
scrollProvider.SetScrollPercent(percent,
System.Windows.Automation.ScrollPatternIdentifiers.NoScroll);
break;
}
The Code
Here is the code with all the necessary extension methods:
public static class DataGridScrollExtensions
{
/// <summary>
/// Scroll to the start of the ScrollBar.
/// <param name="mode"></param>
public static void ScrollToStart(this DataGrid grid, ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
grid.ScrollToPercent(ScrollMode.Vertical, 0);
break;
case ScrollMode.Horizontal:
grid.ScrollToPercent(ScrollMode.Horizontal, 0);
break;
}
}
/// <summary>
/// Scroll to the end of the ScrollBar.
/// </summary>
/// <param name="mode"></param>
public static void ScrollToEnd(this DataGrid grid, ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
grid.ScrollToPercent(ScrollMode.Vertical, 100);
break;
case ScrollMode.Horizontal:
grid.ScrollToPercent(ScrollMode.Horizontal, 100);
break;
}
}
/// <summary>
/// Scroll to a percentage of the scrollbar (50% = half).
/// </summary>
/// <param name="mode"></param>
/// <param name="percent"></param>
public static void ScrollToPercent(this DataGrid grid, ScrollMode mode, double percent)
{
// Fix the percentage.
if (percent < 0)
percent = 0;
else if (percent > 100)
percent = 100;
// Get the scroll provider.
var scrollProvider = GetScrollProvider(grid);
// Scroll.
switch (mode)
{
case ScrollMode.Vertical:
scrollProvider.SetScrollPercent(System.Windows.Automation.ScrollPatternIdentifiers.NoScroll, percent);
break;
case ScrollMode.Horizontal:
scrollProvider.SetScrollPercent(percent, System.Windows.Automation.ScrollPatternIdentifiers.NoScroll);
break;
}
}
/// <summary>
/// Get the current position of the scrollbar.
/// </summary>
/// <param name="mode"></param>
/// <returns></returns>
public static double GetScrollPosition(this DataGrid grid, ScrollMode mode)
{
var scrollBar = grid.GetScrollbar(mode);
return scrollBar.Value;
}
/// <summary>
/// Get the maximum position of a scrollbar.
/// </summary>
/// <param name="mode"></param>
/// <returns></returns>
public static double GetScrollMaximum(this DataGrid grid, ScrollMode mode)
{
var scrollBar = grid.GetScrollbar(mode);
return scrollBar.Maximum;
}
/// <summary>
/// Scroll to a position of the scrollbar.
/// </summary>
/// <param name="mode"></param>
/// <param name="position"></param>
public static void Scroll(this DataGrid grid, ScrollMode mode, double position)
{
// Get the scrollbar and convert the position to percent.
var scrollBar = grid.GetScrollbar(mode);
double positionPct = ((position / scrollBar.Maximum) * 100);
// Scroll to a specfic percentage of the scrollbar.
grid.ScrollToPercent(mode, positionPct);
}
/// <summary>
/// Get a scroll provider for the grid.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
private static IScrollProvider GetScrollProvider(DataGrid grid)
{
var p = FrameworkElementAutomationPeer.FromElement(grid) ?? FrameworkElementAutomationPeer.CreatePeerForElement(grid);
return p.GetPattern(PatternInterface.Scroll) as IScrollProvider;
}
/// <summary>
/// Get one of the grid's scrollbars.
/// </summary>
/// <param name="grid"></param>
/// <param name="mode"></param>
/// <returns></returns>
public static ScrollBar GetScrollbar(this DataGrid grid, ScrollMode mode)
{
if (mode == ScrollMode.Vertical)
return grid.GetScrollbar("VerticalScrollbar");
else
return grid.GetScrollbar("HorizontalScrollbar");
}
/// <summary>
/// Find the scrollbar for our datagrid.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dep"></param>
/// <returns></returns>
private static ScrollBar GetScrollbar(this DependencyObject dep, string name)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dep); i++)
{
var child = VisualTreeHelper.GetChild(dep, i);
if (child != null && child is ScrollBar && ((ScrollBar)child).Name == name)
return child as ScrollBar;
else
{
ScrollBar sub = GetScrollbar(child, name);
if (sub != null)
return sub;
}
}
return null;
}
}
Creating the ScrollDataGrid control
Now that we can control the scrolling we could go even further. What about creating a DataGrid where you can subscribe to both Scroll events or even store the current scroll position? This could be useful for when we're reloading the items and we want to preserve the scroll position.

The most important things to note are the SaveScrollPosition / ReloadScrollPosition methods and the HorizontalScroll / VerticallScroll events. Here is a small demo of the ScrollDataGrid:
The method SaveScrollPosition saves the current position in an internal field and the ReloadScrollPosition applies the value of that field back to the ScrollBar. To find the ScrollBars we're applying an other technique, using GetTemplateChild. The rest of the code calls our extension methods:
public class ScrollDataGrid : DataGrid
{
/// <summary>
/// The vertical scrollbar.
/// </summary>
private ScrollBar verticalScrollBar;
/// <summary>
/// The horizontal scrollbar.
/// </summary>
private ScrollBar horizontalScrollBar;
/// <summary>
/// Position of the vertical scrollbar we saved.
/// </summary>
private double savedVerticalScrollPosition;
/// <summary>
/// Position of the horizontal scrollbar we saved.
/// </summary>
private double savedHorizontalScrollPosition;
/// <summary>
/// Event for each vertical scroll.
/// </summary>
public event EventHandler<ScrollEventArgs> VerticalScroll;
/// <summary>
/// Event for each horizontal scroll.
/// </summary>
public event EventHandler<ScrollEventArgs> HorizontalScroll;
/// <summary>
/// Load the scrollbars after the template gets loaded.
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.LoadScrollBars();
}
/// <summary>
/// Get both scrollbars.
/// </summary>
private void LoadScrollBars()
{
verticalScrollBar = this.GetTemplateChild("VerticalScrollbar") as ScrollBar;
if (verticalScrollBar != null)
verticalScrollBar.Scroll += new ScrollEventHandler(OnVerticalScroll);
horizontalScrollBar = this.GetTemplateChild("HorizontalScrollbar") as ScrollBar;
if (horizontalScrollBar != null)
horizontalScrollBar.Scroll += new ScrollEventHandler(OnHorizontalScroll);
}
/// <summary>
/// Notify that we are scrolling vertically.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnVerticalScroll(object sender, ScrollEventArgs e)
{
if (VerticalScroll != null)
VerticalScroll(sender, e);
}
/// <summary>
/// Notify that we are scrolling horizontally.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnHorizontalScroll(object sender, ScrollEventArgs e)
{
if (HorizontalScroll != null)
HorizontalScroll(sender, e);
}
/// <summary>
/// Save the current scroll position.
/// </summary>
/// <param name="mode"></param>
public void SaveScrollPosition(ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
this.savedVerticalScrollPosition = verticalScrollBar.Value;
break;
case ScrollMode.Horizontal:
this.savedHorizontalScrollPosition = horizontalScrollBar.Value;
break;
default:
break;
}
}
/// <summary>
/// Reload the scroll position that was saved before.
/// </summary>
/// <param name="mode"></param>
public void ReloadScrollPosition(ScrollMode mode)
{
switch (mode)
{
case ScrollMode.Vertical:
this.Scroll(ScrollMode.Vertical, savedVerticalScrollPosition);
break;
case ScrollMode.Horizontal:
this.Scroll(ScrollMode.Horizontal, savedHorizontalScrollPosition);
break;
}
}
}
Downloads
Happy scrolling..
Code metrics and more with NDepend
Introduction
Do you know the quality of the project you're currently working on? Sure you can have guidelines and rules... but projects where a few people have worked on for a few weeks/months/years tend to live their own life here and there. Maybe the team had to catch a deadline for the latest sprint, or the lead developer was on holiday and the problem had to be solved using a quick and dirty solution, ... Every project will have its own little exceptions to the rules and guidelines.
But it should be possible at a certain point in time to measure how good (or how bad) the project is being developed. And this is where NDepend comes in. Quote from the NDepend site:
NDepend is a Visual Studio tool to manage complex .NET code and achieve high Code Quality. With NDepend, software quality can be measured using Code Metrics, visualized using Graphs and Treemaps, and enforced using standard and custom Rules.
Hence the software design becomes concrete, code reviews are effective, large refactoring are easy and evolution is mastered.
Installation
To install NDepend you just download a zip file, install it, copy your license in the root of the directory (if you have one) and you're done. Afterwards you have to go and read QuickStartTutorial_NDepend.txt to see how you can install the Visual Studio addin. This is a personal choice but I'm not too fond of XCOPY deployment. I would rather have had a regular setup wizard where I could just check or uncheck the Visual Studio 2010 integration.
Patrick Smacchia (the creator of NDepend) wrote a nice article regarding why he chose XCOPY deployment: http://codebetter.com/blogs/patricksmacchia/archive/2009/08/10/the-benefits-of-xcopy-deployment.aspx
Now that I installed the application and the AddIn we can continue.
Mode 1: VisualNDepend
In the NDepend directory you'll find the file VisualNDepend.exe, this is the standalone application.
Since NDepend uses DevExpress as control library you can easely make a few changes to the UI. I decided to go for the black ribbon, here is the result:

In the rest of the article I'll be using the standalone application.
Mode 2: NDepend AddIn
NDepend also integrates with Visual Studio 2010. It doesn't seem to provide extra functionality but it integrates very well with the solution you're currently working on.

Also when you right click a project you get tons of functionalities that directly apply to that project:

Analyzing a real project
I'm currently working on an ASP.NET project that was completed about a year ago. The goal here is to start refactoring so that we can easily move to Silverlight in the future. NDepend is based on analysis of assemblies, but when you create a new NDepend project you can also open a Visual Studio solution which will in turn add all projects as assemblies to be analysed.

After loading the solution the external references will also be resolved automatically. And that's it. Now you can hit the button Run Analysis to get started. After a few seconds / minutes the analysis will be done and you'll have a complete overview of your solution.
HTML Report
The first thing you'll see is an HTML report containing all the information:
- Overview of the application metrics
- Overview of the assembly metrics
- A VisualNDepend view
- An assembly dependencies diagram
- And much much more!
The fact that the report is generated automatically is great (we're working with SharePoint to store all our documents). If you're working with a team at your customer you can easily share the analysis report with the local team.

Code Query Language
NDepend introduces the concept of Code Query Language (CQL). This language allows you to create reports of the analysis as if you were working with SQL.
WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE
CyclomaticComplexity > 20
ORDER BY CyclomaticComplexity DESC
Just like Visual Studio comes with a standard set of snippets, NDepends comes with a standard set of queries (more than 100!).

Analyzing the output of a query
The set of standard queries contains a lot of interesting queries you can use for each project. One of the most interesting is the query Do not raise too general exception types. It's true that when you want to do some quick tests or you're not that experienced with exception handling you tend to use Exception a lot. But it is a best pratice to use your own type (for example CreditLimitReachedException) instead of the default Exception / ApplicationException.

When I ran the query NDepend provided me with the list of methods that were using these global exceptions:

After double clicking a method NDepend will bring up Visual Studio, open the right file and jump to the right line. You can start fixing your code right away!

In the introduction I talked about rules and guidelines. Well, thanks to CQL the person in charge could create some queries that check if the rules and guidelines are followed correctly.
Code Coverage
An other great functionality of NDepend is that you can track your code coverage. When you're writing unit tests you want to be sure that your tests cover all the code. NDepend will give you a visual overview of all your methods and their coverage and you can even create reports. This is useful for when you want to find all methods with a coverage percent less than 50, create a report out of this data and sent it to your test team:

Much more
I covered a few interesting features of NDepend but there's still much more to discover:
- Dependency Graph
- Dependency Matrix
- Visual Metrics
- Comparing with previous analysis (to see how the project evolved)
- MSBuild integration!
- ...
Documentation
Blogs and documents:
Videos:
Alternatives
The only alternative to NDepend I know is Microsoft's FxCop. A great feature of FxCop is its integration with TFS.
Conclusion
NDepend is a great application with an unbelievable amount of features. Everything you see in the application can be exported one way or the other (be it HTML, PNG, XLS, ...) which is great. Seeing visual representations of the analysis will also help you get a better view of things. And with CQL you can really enforce your company's own rules and guidelines throughout multiple projects. The code coverage support is great and I truly love the MSBuild integration.
I'm a happy user!
And finally since I'm a big MSBuild fan I might write an article in the future that handles the integration of NDepend with MSBuild/TFS/TeamCity/SharePoint...
Enjoy...
Some clarity on auto loading Visual Studio 2010 Extensions
Introduction
Visual Studio 2010 Extensions (VSIX) are great for adding the functionality you need to Visual Studio 2010. With an SDK, easy-to-understand API, support for WPF and tons of examples (http://code.msdn.microsoft.com/vsx) it's also a great platform for developers.
In most cases you'll want to build an extension that does something when you click a button, when you type something, ... and this is also the default behavior of your package. The method Initialize() will only be invoked when your action triggers it. So don't worry if Initialize() doesn't get called when Visual Studio starts because this is default behavior.
But what if you want Initialize() to be called when Visual Studio starts? In previous versions of Visual Studio you had the RegisterAutoLoadAttribute which has now been made obsolete.
Auto loading with ProvideAutoLoadAttribute
Visual Studio 2010 comes with this new attribute, the ProvideAutoLoadAttribute. If you decorate your Package with this attribute you'll be able to configure the auto loading process. Here's an example of how you can configure this:
[ProvideAutoLoad("ADFC4E64-0397-11D1-9F4E-00A0C911004F")]
public sealed class MyPackage : Package
The attribute requires you to pass a Guid. This Guid stands for the context in which you want your extension to start. In the following listyou can find a list of all available contexts:
- UICONTEXT_CodeWindow: 8FE2DF1D-E0DA-4EBE-9D5C-415D40E487B5
Specifies a UI context in which the code window is active.
- UICONTEXT_Debugging: ADFC4E61-0397-11D1-9F4E-00A0C911004F
Specifies The UI context for debugging mode.
- UICONTEXT_DesignMode: ADFC4E63-0397-11D1-9F4E-00A0C911004F
Specifies the UI context for design mode.
- UICONTEXT_Dragging: B706F393-2E5B-49E7-9E2E-B1825F639B63
Specifies a UI context in which a drag/drop operation is active.
- UICONTEXT_EmptySolution: ADFC4E65-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which an empty solution is active.
- UICONTEXT_FullScreenMode: ADFC4E62-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which the Full Screen mode of the view is active.
- UICONTEXT_NoSolution: ADFC4E64-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which no solution is open.
- UICONTEXT_SolutionBuilding: ADFC4E60-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which the solution is being built.
- UICONTEXT_SolutionExists: F1536EF8-92EC-443C-9ED7-FDADF150DA82
Specifies a UI context in which a solution exists.
- UICONTEXT_SolutionHasMultipleProjects: 93694FA0-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which a solution is open and has multiple projects loaded.
- UICONTEXT_SolutionHasSingleProject: ADFC4E66-0397-11D1-9F4E-00A0C911004F
Specifies a UI context in which a solution with a single project is open.
More Information