Adding a “Open the containing folder” command to Visual Studio.Net 2003

Resources

I work for one of the popular job board companies and we still have some many projects written in .Net 1.1. I often use Visual Studio 2003, and whenever I use it, I miss all handy commands on Visual Studio 2008 such as “Open the containing folder.”As a developer who loves developing small program for his use, I myself finally decided to add “Open the containing folder” and a few other stuff to Visual Studio 2003.

First, you have to figure out the window name. You can do that using “Command Browser” which is one of those useful visual studio.net add-on development samples. The name for source code editor tab is “Easy MDI Document Window.”

Opening a folder is relatively easy. You can just call Process.Start like this

System.Diagnostics.Process.Start(_application.ActiveDocument.Path);

The tricky thing was to add command to the tab. I used AddNamedCommand(…). Often, it returned an error similar to “The name already exists” error. So, I tried commands.Item(…) to check if the command already exist, yet this returned an error if the command does not exsit. I had to next try and catch blocks on connect.

try
{
    _iisRecycleCommand = commands.Item(“ExtVS2003.Connect.ExtVS2003”, -1);
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
    try
    {
        if (_iisRecycleCommand == null)
        {
            _iisRecycleCommand = commands.AddNamedCommand(addInInstance, “ExtVS2003”, “Recycle IIS App pools”, “Reset IIS”, true, bitmapNo,
                ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled);
            CommandBar cbTools = commandBars[“Tools”];
            //commandBars[“Tools”].Controls[0].Caption
            CommandBarControl cbcTools = _iisRecycleCommand.AddControl(cbTools, 1);
        }
    }
    catch (Exception ex) { Console.WriteLine(ex.Message);}
}

try
{
    _openContainingFolderCommand = commands.Item(“ExtVS2003.Connect.OpenContainingFolder”, -1);
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
    try
    {
        if (_openContainingFolderCommand == null)
        {
            _openContainingFolderCommand = commands.AddNamedCommand(addInInstance, “OpenContainingFolder”, “Open the containing folder”,
                “Open the containing folder”, true, 0, ref contextGUIDS,
                (int) vsCommandStatus.vsCommandStatusSupported +
                (int) vsCommandStatus.vsCommandStatusEnabled);
            CommandBar cbEasyMDIWindow = commandBars[“Easy MDI Document Window”];
            CommandBarControl cbcEasyMDIWIndow = _openContainingFolderCommand.AddControl(cbEasyMDIWindow, 1);
        }
    }
    catch (Exception ex) { Console.WriteLine(ex.Message);}
}

It finally works now and this is the full source code

using System.DirectoryServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace ExtVS2003
{
    using System;
    using Microsoft.Office.Core;
    using Extensibility;
    using System.Runtime.InteropServices;
    using EnvDTE;

    #region Read me for Add-in installation and setup information.
    // When run, the Add-in wizard prepared the registry for the Add-in.
    // At a later time, if the Add-in becomes unavailable for reasons such as:
    //   1) You moved this project to a computer other than which is was originally created on.
    //   2) You chose ‘Yes’ when presented with a message asking if you wish to remove the Add-in.
    //   3) Registry corruption.
    // you will need to re-register the Add-in by building the MyAddin21Setup project
    // by right clicking the project in the Solution Explorer, then choosing install.
    #endregion

    ///

    ///   The object for implementing an Add-in.
    ///

    ///
    [GuidAttribute(“594C22F4-C9ED-40B1-9CC7-2D095D68AD97”), ProgId(“ExtVS2003.Connect”)]
    public class Connect : Object, IDTExtensibility2, IDTCommandTarget
    {
        const string OUTPUTWINDOWGUID = “{1BD8A850-02D1-11D1-BEE7-00A0C913D1F8}”;
        private _DTE _application;
        private AddIn addInInstance;
        private Command _iisRecycleCommand, _openContainingFolderCommand;
        private OutputWindowPane _outputWindowPane;
        private BuildEvents _buildEvents;

        ///

        ///        Implements the constructor for the Add-in object.
        ///        Place your initialization code within this method.
        ///

        public Connect()
        {
        }

        ///

        ///      Implements the OnConnection method of the IDTExtensibility2 interface.
        ///      Receives notification that the Add-in is being loaded.
        ///

        ///         ///      Root object of the host application.
        ///         ///         ///      Describes how the Add-in is being loaded.
        ///         ///         ///      Object representing this Add-in.
        ///         ///
        public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {
            int bitmapNo = 59;
            _application = (_DTE)application;
            addInInstance = (AddIn)addInInst;

            SetBuildEvent();
            SetOutputWindowPane();

            if (connectMode == ext_ConnectMode.ext_cm_Startup)
            {
                object []contextGUIDS = new object[] { };
                Commands commands = _application.Commands;
                _CommandBars commandBars = _application.CommandBars;

                // When run, the Add-in wizard prepared the registry for the Add-in.
                // At a later time, the Add-in or its commands may become unavailable for reasons such as:
                //   1) You moved this project to a computer other than which is was originally created on.
                //   2) You chose ‘Yes’ when presented with a message asking if you wish to remove the Add-in.
                //   3) You add new commands or modify commands already defined.
                // You will need to re-register the Add-in by building the ExtVS2003Setup project,
                // right-clicking the project in the Solution Explorer, and then choosing install.
                // Alternatively, you could execute the ReCreateCommands.reg file the Add-in Wizard generated in
                // the project directory, or run ‘devenv /setup’ from a command prompt.
                try
                {

                    try
                    {
                        _iisRecycleCommand = commands.Item(“ExtVS2003.Connect.ExtVS2003”, -1);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        try
                        {
                            if (_iisRecycleCommand == null)
                            {
                                _iisRecycleCommand = commands.AddNamedCommand(addInInstance, “ExtVS2003”, “Recycle IIS App pools”, “Reset IIS”, true, bitmapNo,
                                    ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled);
                                CommandBar cbTools = commandBars[“Tools”];
                                //commandBars[“Tools”].Controls[0].Caption
                                CommandBarControl cbcTools = _iisRecycleCommand.AddControl(cbTools, 1);
                            }
                        }
                        catch (Exception ex) { Console.WriteLine(ex.Message);}
                    }

                    try
                    {
                        _openContainingFolderCommand = commands.Item(“ExtVS2003.Connect.OpenContainingFolder”, -1);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        try
                        {
                            if (_openContainingFolderCommand == null)
                            {
                                _openContainingFolderCommand = commands.AddNamedCommand(addInInstance, “OpenContainingFolder”, “Open the containing folder”,
                                    “Open the containing folder”, true, 0, ref contextGUIDS,
                                    (int) vsCommandStatus.vsCommandStatusSupported +
                                    (int) vsCommandStatus.vsCommandStatusEnabled);
                                CommandBar cbEasyMDIWindow = commandBars[“Easy MDI Document Window”];
                                CommandBarControl cbcEasyMDIWIndow = _openContainingFolderCommand.AddControl(cbEasyMDIWindow, 1);
                            }
                        }
                        catch (Exception ex) { Console.WriteLine(ex.Message);}
                    }

                }
                catch(Exception ex)
                {
                    MessageBox.Show(“Cant’t place toolbutton, error: ” + ex.Message, “error”, MessageBoxButtons.OK);
                }
            }

        }

        private void SetOutputWindowPane()
        {
            OutputWindow outputWindow = (OutputWindow)_application.Windows.Item(Constants.vsWindowKindOutput).Object;
            _outputWindowPane = outputWindow.OutputWindowPanes.Item(OUTPUTWINDOWGUID);
        }

        private void SetBuildEvent()
        {
            _buildEvents = _application.Events.BuildEvents;
            _buildEvents.OnBuildDone += new _dispBuildEvents_OnBuildDoneEventHandler(_buildEvents_OnBuildDone);
            _buildEvents.OnBuildProjConfigDone += new _dispBuildEvents_OnBuildProjConfigDoneEventHandler(_buildEvents_OnBuildProjConfigDone);
        }

        ///

        ///     Implements the OnDisconnection method of the IDTExtensibility2 interface.
        ///     Receives notification that the Add-in is being unloaded.
        ///

        ///         ///      Describes how the Add-in is being unloaded.
        ///         ///         ///      Array of parameters that are host application specific.
        ///         ///
        public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
        {
            try
            {
                _iisRecycleCommand.Delete();
                _openContainingFolderCommand.Delete();
            }
            catch (Exception ex)
            {
                MessageBox.Show(“Error in Disconnect: ” + ex.Message, “Error”, MessageBoxButtons.OK);
            }

        }

        ///

        ///      Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
        ///      Receives notification that the collection of Add-ins has changed.
        ///

        ///         ///      Array of parameters that are host application specific.
        ///         ///
        public void OnAddInsUpdate(ref Array custom)
        {
        }

        ///

        ///      Implements the OnStartupComplete method of the IDTExtensibility2 interface.
        ///      Receives notification that the host application has completed loading.
        ///

        ///         ///      Array of parameters that are host application specific.
        ///         ///
        public void OnStartupComplete(ref Array custom)
        {
        }

        ///

        ///      Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
        ///      Receives notification that the host application is being unloaded.
        ///

        ///         ///      Array of parameters that are host application specific.
        ///         ///
        public void OnBeginShutdown(ref Array custom)
        {
        }

        ///

        ///      Implements the QueryStatus method of the IDTCommandTarget interface.
        ///      This is called when the command’s availability is updated
        ///

        ///         ///        The name of the command to determine state for.
        ///         ///         ///        Text that is needed for the command.
        ///         ///         ///        The state of the command in the user interface.
        ///         ///         ///        Text requested by the neededText parameter.
        ///         ///
        public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
        {
            if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
            {
                switch (commandName)
                {
                    case “ExtVS2003.Connect.ExtVS2003”:
                        status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                        break;

                    case “ExtVS2003.Connect.OpenContainingFolder”:
                        status  = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                        break;
                }
            }
        }

        ///

        ///      Implements the Exec method of the IDTCommandTarget interface.
        ///      This is called when the command is invoked.
        ///

        ///         ///        The name of the command to execute.
        ///         ///         ///        Describes how the command should be run.
        ///         ///         ///        Parameters passed from the caller to the command handler.
        ///         ///         ///        Parameters passed from the command handler to the caller.
        ///         ///         ///        Informs the caller if the command was handled or not.
        ///         ///
        public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
        {
            handled = false;
            if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
            {
                switch (commandName)
                {
                    case “ExtVS2003.Connect.ExtVS2003”:
                        RecycleAllApplicationPools();
                        handled = true;
                        break;

                    case “ExtVS2003.Connect.OpenContainingFolder”:
                        OpenContainingFolder();
                        handled = true;
                        break;
                }
            }
        }

        private void OpenContainingFolder()
        {
            System.Diagnostics.Process.Start(_application.ActiveDocument.Path);
        }

        private void _buildEvents_OnBuildDone(vsBuildScope Scope, vsBuildAction Action)
        {
            if (IsBuildingGACProject())
            {
                RecycleAllApplicationPools();
            }
        }

        private void _buildEvents_OnBuildProjConfigDone(string Project, string ProjectConfig, string Platform, string SolutionConfig,
            bool Success)
        {
            if (!Success)
            {
                _application.ExecuteCommand(“Build.Cancel”, string.Empty);
            }
        }

        private bool IsBuildingGACProject()
        {
            Regex GACRegex = new Regex(“PJB.UI|PJB.Business”, RegexOptions.IgnoreCase);
            Projects projects = _application.Solution.Projects;

            foreach (Project project in projects)
            {
                if (GACRegex.Match(project.Name).Success)
                {
                    return true;
                }
            }
            return false;
        }

        private void RecycleAllApplicationPools()
        {
            DirectoryEntry appPools = new DirectoryEntry(“IIS://localhost/W3SVC/AppPools”);
            _outputWindowPane.OutputString(“——————————————-\n”);
            _outputWindowPane.OutputString(“Start recycling application pools.”);
            foreach (DirectoryEntry appPool in appPools.Children)
            {
                appPool.Invoke(“Recycle”, null);
                _outputWindowPane.OutputString(“.”);
            }
            _outputWindowPane.OutputString(” completed.\n”);
        }

    }
}

Adding a “Open the containing folder” command to Visual Studio.Net 2003

One thought on “Adding a “Open the containing folder” command to Visual Studio.Net 2003

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s