September 2010 - Posts

Add and Remove list of references the ultra simple way

When you use VS to initially create a project based on any of the several templates available like Class Library, WPF Application, Web Application, Office Addin and the list goes on, you already get some of the basic ‘must have’ references for your project automatically added thanks to the templating mechanism, i.e. you get PresentationCore.dll et friends added to your project every time you create a WPF-based project.

Now this is good only as a starting skeleton. You will have to add a few more assemblies as soon as you start coding.

Some of them will be core .NET fx references that the template just didn’t add (i.e. you’ve a WPF based app where you need to use some WinForms bit or viceversa) and some of them will probably include some 3rd party framework you may be using (i.e. log4net, NHibernate, etc).

This adding of references can get a bit tedious over time as you find yourself adding the same set of references over and over again… every time you create a new project…

Even if you’re using the super-cool Search References from which you can easily search and add multiple references with a few clicks, this is still far from being ideal… ideal would be to say add my “Commonly used web stuff” or add my “log4net and NHibernate” (in a single shoot!).

Enter the free World of VS Reference Lists extension. (yes, free, go download it here).

Let’s create a new Web Application project and see how the “References” node looks like:

RefLists1


Let’s now use the ultra cool Search References extension to filter the list of available references to those that start with “system.web” and select the following four assemblies which are not added by default by VS and we supposedly used in every Web App project we develop:

RefLists2

Once we have added these references we will create a named list to group them together:

RefLists3

(Note how the extension is clever enough to find a common prefix for all selected assemblies and offer us “System.Web” as the name for the list to be created)

We won’t choose the “System.Web” suggested name as we want to have a more personalized list name…

RefLists4

We’ve just created our list that we can now use in any other Web App project where these references haven’t been added yet:

RefLists6

The extension also makes it very easy to manage existing lists, let’s say we mistakenly included “System.Web.Routing.dll” to our list, just click on it and remove it from our list:

RefLists7

Pretty cool extension, ugh?

You can download it for free and start creating your list of references today!

And if you would like to have Microsoft to include such a feature in the next version of Visual Studio be sure you vote this suggestion in Connect.

Inside the “Default Browser Switcher” extension

You may have already heard of the recently WoVS extension “Default Browser Switcher” (download from Visual Studio Gallery or from Extension Manager inside VS) that helps in choosing what browser you want to launch from VS while debugging your ASP.NET applications.

You can start by reading the original post from Scott Hanselman where he describes some interesting inner workings of VS related to how it handles the launching of the VS default browser. Note this is the default browser to be launched from VS which may or may not be your default system-wide browser.

If you’re brave enough to survive Scott’s post then you’re ready to enter some even more obscure details: how to package that into an extension for Visual Studio…

We started by defining the set of commands we wanted to support and we ended up with ten commands total. That is a “Set default Browser to X” command multiplied by Internet Explorer, Firefox, Chrome, Safari and Opera and a “View in Browser X” command multiple by the same number of browsers. The first set would go into a VS Toolbar and the second set would go into a sub menu whose parent would be a new “View in Browser” command.

To author the UI we used the very handy and friendly VSPackage Builder which allowed us to quickly design our 10 commands and place them where we wanted inside VS:

DBS-Builder

 

(Yes, that’s a DSL for authoring your own custom UI inside VS!)

An interesting bit is that we’ve to make sure the TextChanges flag was set on each command as we wanted the ability to dynamically change the command’s original text at runtime:

image

We do this so we can show different tooltips at runtime for the same command. We show the “Set X as the default browser” when that browser happens to not be the default one already:

image

And then we show “X is the default browser” when you hover over the current default one:

image

From the coding side all what’s needed is to properly set the Text property of the given MenuCommand to whatever text you want. In our case, it looks like this:

command.Text = IsDefaultBrowser ? String.Format("{0} is the default browser", browserName) : String.Format("Set {0} as the default browser", browserName);

We also added a new “View in Browser” command which we wanted to sit next to the built-in one so we had to use a submenu which ended up looking like this:

image

This was produced using a model like the following:

 

image

Where we have a group of commands belonging to our menu which is then placed on different built-in groups, like in the File top-level menu and in the text editor’s context menu.

Besides our fancy UI we also have some black magic code, like the one used to retrieve the currently selected item:

Start by retrieving the selection service:

var selService = GetService(typeof(SVsShellMonitorSelection)) as IVsMonitorSelection;

And call its GetCurrentSelection method which happens to have a lovely signature:

int GetCurrentSelection(
	out IntPtr ppHier,
	out uint pitemid,
	out IVsMultiItemSelect ppMIS,
	out IntPtr ppSC
)

Assuming you’ve a previous unmanaged C++ background it is really easy to figure out what each one of these parameters mean <g>. Just in case you don’t, here is the cheat sheet: pointers and pointers to pointers.

ppHier – returns the currently selected hierarchy (or null if it happen to be more than one selected)

pitemid – pointer to the itemid of the selected item (this is just a cookie you can else on another 500 methods to return meaninful information)

These are the two parameters we’re most interested in. if pitemid doesn’t return VSITEMID_SELECTION it means there isn’t a multiple selection, so we can safely grab ppHier as being our target selected item.

Once we have that guy identified we can add a bit more magic to get to an instance of an automation project which will allows us to better examine what the current project is about:

ppHier.GetProperty((uint)Microsoft.VisualStudio.VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj);

Actually before doing so I need to convert my pointer (ppHier IntPtr) to an IVsHierarchy, piece of cake:

var hier = Marshal.GetTypedObjectForIUnknown(ppHier, typeof(IVsHierarchy)) as IVsHierarchy;

And now yes, ask for the VSHPROPID_ExtObject:

var hier = Marshal.GetTypedObjectForIUnknown(ppHier, typeof(IVsHierarchy)) as IVsHierarchy;

You: Victor, are we there yet???
Me: Almost.

Now let’s release the COM interface we don’t want to keep handing around:

Marshal.Release(ppHier);

And cast the hierarchy to an EnvDTE.Project type:

var project = hier as EnvDTE.Project; 

Just to drop the last bit of magic which will cause a property named Object to return to us a VSProject type:

var vsproject = project.Object as VSLangProj.VSProj;

I could keep going and going but I’m guessing you had enough for now!

We can only hope that all this code gets simplified in the next version of VS by using MEF and nicely designed APIs.

Hope you enjoy this extension!

More Posts