Logo
HOWTO: Get assemblies of the Add Reference dialog from a Visual Studio add-in.

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio 2005
Date: August 2012   Microsoft Visual Studio 2008
      Microsoft Visual Studio 2010
      Microsoft Visual Studio 2012
Introduction

This article explains how to get the list of assemblies that Visual Studio shows in the .NET tab of the Add Reference dialog (Project, Add Reference... menu).

More information

The .NET tab of the Add Reference dialog doesn't show assemblies in the Global Assembly Cache (GAC), but assemblies located in some specific folders. The GAC is a deployment mechanism (to locate shared assemblies from deployed applications), it is not a repository of assemblies to be used at development time. Instead, the Add Reference dialog shows assemblies located in the folder of the .NET Framework:

  • Folder returned by the System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() function (for example "C:\Windows\Microsoft.NET\Framework\v4.0.30319\")

and in additional folders that are specified in the Windows registry:

  • Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders
  • Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx
  • Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v3.5\AssemblyFoldersEx
  • Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx
  • Subkeys of HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.5.50709\AssemblyFoldersEx

Note 1: old Visual Studio versions used also the KEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\<version>\AssemblyFolders registry entry, but Visual Studio 2005 and higher don't use it any more.

Note 2: if you are using regedit.exe and Windows 64-bit, go to the HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework registry key, which is the 32-bit view. But programmatically from an add-in use the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework registry entry because Visual Studio is a 32-bit application.

Note 3: not all Visual Studio versions can target all .NET Framework versions. The available .NET Framework versions for eahc Visual Studio versions are the following:

  • Visual Studio 2005 can target .NET Framework 2.0.
  • Visual Studio 2008 can target .NET Framework 2.0, 3.0 and 3.5.
  • Visual Studio 2010 can target .NET Framework 2.0, 3.0, 3.5 and 4.0.
  • Visual Studio 2012 can target .NET Framework 2.0, 3.0, 3.5, 4.0 and 4.5.

The following sample shows the code of an add-in that shows in the Immediate window information the assemblies of those folders:

Language: VB.NET   Copy Code Copy Code (IE only)
Imports System
Imports Microsoft.VisualStudio.CommandBars
Imports Extensibility
Imports EnvDTE
Imports EnvDTE80
Imports Microsoft.Win32

Public Class Connect
   Implements IDTExtensibility2	

   Private _applicationObject As DTE2
   Private _addInInstance As AddIn

   Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, _
      ByRef custom As Array) Implements IDTExtensibility2.OnConnection

      _applicationObject = CType(application, DTE2)
      _addInInstance = CType(addInInst, AddIn)

      Select Case connectMode

         Case ext_ConnectMode.ext_cm_AfterStartup

            ShowAssemblies()

         Case ext_ConnectMode.ext_cm_Startup

            ' OnStartupComplete will be called

      End Select

   End Sub

   Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef custom As Array) _
      Implements IDTExtensibility2.OnDisconnection
   End Sub

   Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
   End Sub

   Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete

      ShowAssemblies()

   End Sub

   Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
   End Sub

   Private Sub ShowAssemblies()

      Const NETFRAMEWORK_ASSEMBLY_FOLDERS As String = "SOFTWARE\Microsoft\.NETFramework\AssemblyFolders"
      Const NETFRAMEWORK As String = "SOFTWARE\Microsoft\.NETFramework"

      Dim assemblyFolder As String

      ' Get the .NET Framework runtime folder
      assemblyFolder = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
      ShowAssembliesFromFolder(assemblyFolder)

      ' Get the .NET Framework assembly folders
      ShowAssembliesFromFolders(NETFRAMEWORK_ASSEMBLY_FOLDERS)

      ' Get the .NET Framework version-specific assembly folders
      Select Case _applicationObject.RegistryRoot.ToUpper()

         Case "SOFTWARE\MICROSOFT\VISUALSTUDIO\8.0"
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v2.0.50727\AssemblyFoldersEx")

         Case "SOFTWARE\MICROSOFT\VISUALSTUDIO\9.0"
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v2.0.50727\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v3.5\AssemblyFoldersEx")

         Case "SOFTWARE\MICROSOFT\VISUALSTUDIO\10.0"
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v2.0.50727\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v3.5\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v4.0.30319\AssemblyFoldersEx")

         Case "SOFTWARE\MICROSOFT\VISUALSTUDIO\11.0"
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v2.0.50727\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v3.5\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v4.0.30319\AssemblyFoldersEx")
            ShowAssembliesFromFolders(NETFRAMEWORK & "\v4.5.50709\AssemblyFoldersEx")

      End Select

   End Sub

   Private Sub ShowAssembliesFromFolders(ByVal registrySubKey As String)

      Dim registryKey As RegistryKey = Nothing
      Dim subkeys As String()
      Dim subKey As String
      Dim assemblyFolder As String

      Try

         registryKey = Registry.LocalMachine.OpenSubKey(registrySubKey, False)

         subkeys = registryKey.GetSubKeyNames()

         If Not (subkeys Is Nothing) Then

            For Each subKey In subkeys

               assemblyFolder = Registry.GetValue("HKEY_LOCAL_MACHINE\" & registrySubKey & "\" & subKey, "", "").ToString()

               ShowAssembliesFromFolder(assemblyFolder)

            Next

         End If

      Catch ex As Exception

      Finally

         If Not registryKey Is Nothing Then
            registryKey.Close()
         End If

      End Try

   End Sub

   Private Sub ShowAssembliesFromFolder(ByVal assemblyFolder As String)

      Dim assemblyFileFullName As String

      If IO.Directory.Exists(assemblyFolder) Then

         Debug.WriteLine("Assemblies of folder " & assemblyFolder)

         For Each assemblyFileFullName In IO.Directory.GetFiles(assemblyFolder, "*.dll")

            Debug.WriteLine(assemblyFileFullName)

         Next

      End If

   End Sub

End Class
Language: C#   Copy Code Copy Code (IE only)
using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using System.Diagnostics;
using Microsoft.Win32;

namespace MyAddIn
{

   public class Connect : IDTExtensibility2
	{
      private DTE2 _applicationObject;
      private AddIn _addInInstance;
      
      public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
		{
			_applicationObject = (DTE2)application;
			_addInInstance = (AddIn)addInInst;

         switch (connectMode)
         {
            case ext_ConnectMode.ext_cm_AfterStartup:
               ShowAssemblies();
               break;
            case ext_ConnectMode.ext_cm_Startup:
               // OnStartupComplete will be called
               break;
         }
		}

		public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
		{
		}

		public void OnAddInsUpdate(ref Array custom)
		{
		}

		public void OnStartupComplete(ref Array custom)
		{
         ShowAssemblies();
		}

		public void OnBeginShutdown(ref Array custom)
		{
		}

      private void ShowAssemblies()
      {
         const string NETFRAMEWORK_ASSEMBLY_FOLDERS = @"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders";
         const string NETFRAMEWORK = @"SOFTWARE\Microsoft\.NETFramework";

         string assemblyFolder;

         // Get the .NET Framework runtime folder
         assemblyFolder = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
         ShowAssembliesFromFolder(assemblyFolder);

         // Get the .NET Framework assembly folders
         ShowAssembliesFromFolders(NETFRAMEWORK_ASSEMBLY_FOLDERS);

         // Get the .NET Framework version-specific assembly folders
         switch (_applicationObject.RegistryRoot.ToUpper())
         {
            case @"SOFTWARE\MICROSOFT\VISUALSTUDIO\8.0":
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v2.0.50727\AssemblyFoldersEx");
               break;

            case @"SOFTWARE\MICROSOFT\VISUALSTUDIO\9.0":
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v2.0.50727\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v3.5\AssemblyFoldersEx");
               break;

            case @"SOFTWARE\MICROSOFT\VISUALSTUDIO\10.0":
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v2.0.50727\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v3.5\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v4.0.30319\AssemblyFoldersEx");
               break;

            case @"SOFTWARE\MICROSOFT\VISUALSTUDIO\11.0":
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v2.0.50727\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v3.5\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v4.0.30319\AssemblyFoldersEx");
               ShowAssembliesFromFolders(NETFRAMEWORK + @"\v4.5.50709\AssemblyFoldersEx");
               break;

         }

      }

      private void ShowAssembliesFromFolders(string registrySubKey)
      {
         RegistryKey registryKey = null;
         string[] subkeys;
         string assemblyFolder;

         try
         {
            registryKey = Registry.LocalMachine.OpenSubKey(registrySubKey, false);

            subkeys = registryKey.GetSubKeyNames();

            if (subkeys != null)
            {
               foreach (string subKey in subkeys)
               {
                  assemblyFolder = Registry.GetValue("HKEY_LOCAL_MACHINE\\" + registrySubKey + "\\" + subKey, "", "").ToString();
                  ShowAssembliesFromFolder(assemblyFolder);
               }
            }
         }
         catch
         {
         }
         finally
         {
            if (registryKey != null)
            {
               registryKey.Close();
            }
         }
      }

      private void ShowAssembliesFromFolder(string assemblyFolder)
      {
         if (System.IO.Directory.Exists(assemblyFolder)) 
         {
            Debug.WriteLine("Assemblies of folder " + assemblyFolder);

            foreach ( string assemblyFileFullName in System.IO.Directory.GetFiles(assemblyFolder, "*.dll"))
            {
                 Debug.WriteLine(assemblyFileFullName);
            }
         }
      }
   }
}

Go back to the 'Resources for Visual Studio .NET extensibility' section for more articles like this


Top