I have been working on a CodePlex project over the last month or so that contains a set of extensibility tools. I have just released ReflectorLink 1.0 which is a Visual Studio addin that launches Reflector.
The following is a copy of the Using ReflectorLink 1.0 documentation on the project site.
ReflectorLink is a Visual Studio addin that launches Reflector. Before launching Reflector, it checks to see whether Reflector is already running. If it does find Reflector already running, it will set it as the active application. If Reflector is not found, it will be started (assuming it can be found). After Reflector has been activated/started, additional commands may be sent to it to load assemblies.
ReflectorLink can be invoked from the Tools menu, Solution Explorer context menus or the code document context menu.
Tools menu
Click the Tools menu and select Reflector.

When launching Reflector from the Tools menu, Reflector will be launched with no further action if no solution is loaded. If there is a solution loaded, the binary references of each project will be loaded into Reflector.
Code document
Right-click on a code document and select Reflector.

When launching Reflector from the code document, ReflectorLink will determine if there is a related project that has binary references. Any references found will be loaded into Reflector.
Note: ReflectorLink does not yet support resolving items clicked in the code document. Only the related project is used to determine what to load into Reflector.
Solution Explorer
There are several scenarios where Reflector can be launched in Solution Explorer. These are:
- Solution node
- Project node
- Project References node
- Project Reference node
- Solution Items
In each scenario, the Reflector menu item will only be enabled if binary references can be found. For solution items, the menu item will only be displayed if the solution item selected is an exe or dll file.
Solution node
Right-click on the solution node and select Reflector.

When launching Reflector from a solution node, ReflectorLink will determine the set of binary references for each project in the solution. Any references found will be loaded into Reflector.
Project node
Right-click on a project node and select Reflector.

When launching Reflector from a project node, ReflectorLink will determine the set of binary references for the project. Any references found will be loaded into Reflector.
Project References node
Right-click on the References node in a project and select Reflector.

When launching Reflector from a References node, ReflectorLink will determine the set of binary references for the related project. Any references found will be loaded into Reflector.
Project Reference node
Right-click on a reference node in a project and select Reflector.

When launching Reflector from a reference node, ReflectorLink will determine whether the reference is a binary reference or a project reference. The menu item will be enabled if the reference is a binary reference and will load it into Reflector when launched.

If the reference is a project reference, the menu item will be disabled.
Solution Item node
Right-click on a solution item node that is an exe or dll and select Reflector.

When launching Reflector from a solution item node, ReflectorLink will determine whether the item is an exe or dll file. The menu item will be invisible if the item is not an exe or dll. The selected item will be loaded into Reflector when launched.
ReflectorLink 1.0 can be downloaded from here.
I have written a few addins over the last couple of years and I have always found the object model really painful to deal with. One of the more common problems I have encountered is trying to identify the type of UIHierarchyItem.Object. This is especially common when you deal with the contents of the Solution Explorer window.
I only know of one solution for identifying the real type behind the object. You can make a call out to Microsoft.VisualBasic.Information.TypeName(Object) to attempt to resolve the type. This wasn't always successful and was also a little limited as the object often implements multiple types. I realised that there was a very easy and more comprehensive way of figuring out what types were being implemented.
By using this DebugHelper class in your addin solution, you will be able to figure out the object types. The Conditional attribute ensures that these methods (and calls to them) will not appear in your release build. The method takes a UIHierarchyItem and searches all the publicly available types of all the assemblies in the app domain for types that are implemented by the UIHierarchyItem.Object property.
using System;
using System.Diagnostics;
using System.Reflection;
using EnvDTE;
namespace Neovolve.Extensibility.VisualStudio
{
/// <summary>
/// The <see cref="DebugHelper"/>
/// class is used to help with debugging tasks for Visual Studio addin development.
/// </summary>
/// <remarks>
/// This class was created by Rory Primrose for the
/// <a href="http://www.codeplex.com/NeovolveX" target="_blank">NeovolveX</a>
/// project.
/// </remarks>
public static class DebugHelper
{
/// <summary>
/// Identifies the internal object types.
/// </summary>
/// <param name="item">The item.</param>
[Conditional("DEBUG")]
public static void IdentifyInternalObjectTypes(UIHierarchyItem item)
{
if (item == null)
{
Debug.WriteLine("No item provided.");
return;
}
if (item.Object == null)
{
Debug.WriteLine("No item object is available.");
return;
}
// Loop through all the assemblies in the current app domain
Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
// Loop through each assembly
for (Int32 index = 0; index < loadedAssemblies.Length; index++)
{
// Assume that the assembly to check against is EnvDTE.dll
IdentifyInternalObjectTypes(item, loadedAssemblies[index]);
}
}
/// <summary>
/// Identifies the internal object types.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="assemblyToCheck">The assembly to check.</param>
[Conditional("DEBUG")]
public static void IdentifyInternalObjectTypes(UIHierarchyItem item, Assembly assemblyToCheck)
{
// Get the types that are publically available
Type[] exportedTypes = assemblyToCheck.GetExportedTypes();
// Loop through each type
for (Int32 index = 0; index < exportedTypes.Length; index++)
{
// Check if the object instance is of this type
if (exportedTypes[index].IsInstanceOfType(item.Object))
{
Debug.WriteLine(exportedTypes[index].FullName);
}
}
}
}
}
Using this debug helper method saved hours if not days in fixing this problem. I hope this helps other people as well.
When it is a EnvDTE.ProjectItem. I must admit that this one took me by surprise.
I am writing a Visual Studio addin for launching Reflector (see the CodePlex project here). You can launch Reflector from the tools menu and the Solution Explorer window and code document context menus. This issue came about when I found a bug in my addin while doing some testing. The scenario encountered was that the binary references for projects in Solution Explorer (the Project node and References node) were not resolved. I had tested this feature in another solution successfully and noticed that the difference between the solutions was that the one with the bug had the projects in solution folders.
After doing some debugging, it turns out that when a project is contained in a solution folder, the UIHierarchyItem.Object value exposed through Solution Explorer is no longer represented by an EnvDTE.Project. It is now an EnvDTE.ProjectItem. Ironically, you must reference ProjectItem.SubProject to get access to the project.
The fact that the project is a project items sub project because its parent is a folder in Solution Explorer is totally confusing.