Logo
HOWTO: Unload a project from a Visual Studio Package

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio 2012
Date: April 2015   Microsoft Visual Studio 2013
      Microsoft Visual Studio 2015
       
Introduction

The automation model (EnvDTE) can unload the selected project in the Solution Explorer executing the "Project.UnloadProject" command, for example using the DTE.ExecuteCommand("Project.UnloadProject") call. This approach requires to select programmatically the project in the Solution Explorer. Furthermore, from a package you may want to avoid the automation model and use the native services. For this purpose, you can use the CloseSolutionElement method of the IVsSolution interface, that allows you to unload the solution, a project or a document. Alternatively, you can use the easier UnloadProject method of the IVsSolution4 interface that was introduced in Visual Studio 2010. This method allows you to specify the Guid of the project that you want to unload and the reason (typically UNLOADSTATUS_UnloadedByUser).

More Information

The following package creates a menu command that, when clicked, unloads the first project of the solution (it assumes that it is loaded):

Language: C#   Copy Code Copy Code (IE only)
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;

namespace MyCompany.MyVSPackage
{
   [PackageRegistration(UseManagedResourcesOnly = true)]
   [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
   [ProvideMenuResource("Menus.ctmenu", 1)]
   [Guid(GuidList.guidMyVSPackagePkgString)]
   public sealed class MyVSPackagePackage : Package
   {
      private const uint VSITEMID_ROOT = 0xFFFFFFFE;

      public MyVSPackagePackage()
      {
      }

      protected override void Initialize()
      {
         CommandID menuCommandID;
         MenuCommand menuItem;

         base.Initialize();

         // Add our command handlers for menu (commands must exist in the .vsct file)
         OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
         if (null != mcs)
         {
            menuCommandID = new CommandID(GuidList.guidMyVSPackageCmdSet, (int)PkgCmdIDList.cmdidUnloadProject);
            menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
            mcs.AddCommand(menuItem);
         }
      }
 
      private void MenuItemCallback(object sender, EventArgs e)
      {
         UnloadFirstSolutionProject();
      }

      private void UnloadFirstSolutionProject()
      {
         IVsSolution4 solution;
         IVsHierarchy projectHierarchy;
         Guid projectGuid;

         // Get the first project of the solution and unload it
         try
         {
            solution = base.GetService(typeof(SVsSolution)) as IVsSolution4;

            // Get the first project of the solution and unload it
            projectHierarchy = GetFirstProjectHierarchy(solution);
            if (projectHierarchy != null)
            {
               projectGuid = GetProjectGuid(projectHierarchy);

               UnloadProject(solution, projectGuid);
            }
         }
         catch (Exception ex)
         {
            System.Windows.Forms.MessageBox.Show(ex.ToString());
         }
      }

      private IVsHierarchy GetFirstProjectHierarchy(IVsSolution4 solution)
      {
         IVsHierarchy solutionHierarchy;
         int hr;
         IntPtr nestedHierarchyValue = IntPtr.Zero;
         uint nestedItemIdValue = 0;
         Guid nestedHierarchyGuid;
         IVsHierarchy projectHierarchy = null;
         uint firstChildNode;
         object value = null;
         
         solutionHierarchy = solution as IVsHierarchy;

         // Get the first visible child node of the solution
         hr = solutionHierarchy.GetProperty(VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, out value);
         ErrorHandler.ThrowOnFailure(hr);

         if (value != null)
         {
            firstChildNode = Convert.ToUInt32(value);

            // Try to get the hierarchy of the node
            nestedHierarchyGuid = typeof(IVsHierarchy).GUID;
            hr = solutionHierarchy.GetNestedHierarchy(firstChildNode, ref nestedHierarchyGuid, 
               out nestedHierarchyValue, out nestedItemIdValue);
            ErrorHandler.ThrowOnFailure(hr);

            if (nestedHierarchyValue != IntPtr.Zero && nestedItemIdValue == VSITEMID_ROOT)
            {
               // Get the new hierarchy
               projectHierarchy = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(nestedHierarchyValue) as IVsHierarchy;
               System.Runtime.InteropServices.Marshal.Release(nestedHierarchyValue);
            }
         }
         return projectHierarchy;
      }

      private Guid GetProjectGuid(IVsHierarchy projectHierarchy)
      {
         Guid projectGuid;
         int hr;

         hr = projectHierarchy.GetGuidProperty(VSITEMID_ROOT, (int) __VSHPROPID.VSHPROPID_ProjectIDGuid, out projectGuid);
         ErrorHandler.ThrowOnFailure(hr);

         return projectGuid;
      }

      private void UnloadProject(IVsSolution4 solution, Guid projectGuid)
      {
         int hr;

         hr = solution.UnloadProject(ref projectGuid, (uint) _VSProjectUnloadStatus.UNLOADSTATUS_UnloadedByUser);
         ErrorHandler.ThrowOnFailure(hr);
      }
   }
}

Related articles



Go to the 'Visual Studio Extensibility (VSX)' web site for more articles like this (Articles section)