Click here to Skip to main content
15,867,756 members
Articles / Programming Languages / C#
Article

Explorer - A Visual Studio 2005 add-in which interacts with Windows Explorer

Rate me:
Please Sign up or sign in to vote.
4.58/5 (38 votes)
16 Jun 2008CPOL5 min read 256.6K   8.1K   136   77
This add-in adds the ability to open Windows Explorer at specified locations and to execute the application in 'Windows Explorer mode'.

Sample Image

Sample Image

Sample Image

Sample Image

Introduction

When I use the Visual Studio environment, sometimes I have to open 'Windows Explorer' in the folder of the solution to do some tasks as copy files, rename files, launch application by double clicking on the executable.

Because my projects aren't at the root of my hard disk, I lose a lot of time. So, one day, I decided to create the 'Explorer' add-in for Visual Studio 2005.

Install the add-in

To install the 'Explorer' add-in:

  1. Copy the Explorer.dll, Explorer.AddIn, Explorer.dll.config, log4net.dll files to your "My Documents\Visual Studio 2005\Addins" folder (create it if it does not exist).
  2. Launch the Visual Studio Environment.
  3. Select the "Tools\Add-in manager" menu and check the Explorer add-in.
That's all...

Using the Add-In

To open 'Windows Explorer' in a specific folder:

  1. In the Solution Explorer window, select the solution (or a project or a folder) and right click on it: An 'Explorer' menu appears.
  2. Select the 'Open folder in Windows Explorer' menu item.

To launch the application as if you double clicked on an '.exe' file in 'Windows Explorer'.

  1. In the Solution Explorer window, select the project and right click on it: An 'Explorer' menu appears.
  2. Select the 'Execute application' menu item.

To collapse all nodes of the solution explorer window

  1. In the Solution Explorer window, select the solution node and right click on it: An 'Explorer' menu appears.
  2. Select the 'Collapse nodes' menu item.

To search help on the web for the current selected source code

  1. In the Code window, select source code and right click on it: An 'Explorer' menu appears.
  2. Select the 'Search help on web' menu item and then the menu item you have defined (Google, Msdn, ...).

Popup Menu Creation

This part is done by the MenuManager.CreatePopupMenu method.

In Visual Studio, the CommandBar interface is used to manage menus. So, first, I have to retrieve the CommandBar object corresponding to the item (of the 'Solution Explorer' window) where I want to add the popup menu. To do it, I use the CommandBars property of the DTE interface like this:

C#
private CommandBar GetCommandBar(string commandBarName)
{
    return ((CommandBars)application.DTE.CommandBars)[commandBarName];
}

where commandBarName is the string "Solution", "Project", "Folder", ... Then, I add the CommandBarPopup corresponding to the 'Explorer' menu to this CommandBar.

C#
CommandBarPopup menu = GetCommandBar(commandBarName).Controls.Add(
     MsoControlType.msoControlPopup, 
     Missing.Value, Missing.Value, 1, true) 
     as CommandBarPopup;

Command Creation

This part is done by the MenuManager.AddCommand method. This method takes a CommandBarPopup, a CommandBase, and a position as parameters, and does the following:

  1. Add the menu item to the CommandBarPopup menu at the specified position.
  2. Create a handler to catch the menu item Click event.
  3. Add the CommandBase to an internal dictionary to be able to retrieve it in the handler method and call the Perform method of this CommandBase.

Menu Item Handlers (details)

When creating the menu items, the MenuItem_Click is added to the list of the handlers of the Click event. In this handler, I get the ID of the menu ('OpenFolder' or 'Execute') and retrieve the right CommandBase object which is contained in the internal dictionary. Then, I call the 'Perform' method to do the work.

C#
private void MenuItem_Click(object commandBarControl, 
        ref bool handled, ref bool cancelDefault)
{
    CommandBarControl menuItem = 
         (CommandBarControl)commandBarControl;
    if (cmdList.ContainsKey(menuItem.Tag))
    {
        cmdList[menuItem.Tag].Perform();
    }
}

OpenFolderCommand

This command is used to open your file manager in a folder corresponding to the selected item in the 'Solution Explorer' window. To do it, I call the Process.Start with the following parameters:

C#
Configuration appConfig = 
   ConfigurationManager.OpenExeConfiguration(
   Assembly.GetExecutingAssembly().Location);
System.Diagnostics.Process.Start(GetFileManagerPath(appConfig), 
   GetParameter(appConfig) + folderPath);
where
  1. GetFileManagerPath() and GetParameter() are used to retrieve (from the app.config file) respectively the full path of the file manager to use (by default 'explorer.exe' => 'Windows Explorer') and parameter (by default "/n,/e" => folder view)
  2. The folder path is found by using the following code :
    C#
    private string GetFilePath(object o)
    {
        if (o is EnvDTE.Solution)
        {
            EnvDTE.Solution solution = (EnvDTE.Solution)o;
            _logger.DebugFormat("The selected item is the '{0}'" + 
                                " solution.", solution.FullName);
            return solution.FullName;
        }
        else if (o is EnvDTE.Project)
        {
            EnvDTE.Project project = (EnvDTE.Project)o;
            _logger.DebugFormat("The selected item is the" + 
                                " '{0}'project.", project.FullName);
            if (IsWebProject(project))
            {
                return 
                  project.Properties.Item("FullPath").Value.ToString() + 
                  "\\";
            }
            else
            {
                return project.FullName;
            }
        }
        else if (o is EnvDTE.ProjectItem)
        {
            EnvDTE.ProjectItem projectItem = (EnvDTE.ProjectItem)o;
                    
            // A 'ProjectItem' can be a sub project, a folder (or a file)
            if (projectItem.SubProject != null)
            {
                return GetFilePath(projectItem.SubProject);
            }
            else
            {
                // we return the full path of the folder (or the file)
                _logger.DebugFormat("The selected item is a '{0}' " + 
                   "folder or a file : ", projectItem.get_FileNames(0));
                return projectItem.get_FileNames(0);
            }
        }
        else
        {
            throw new System.NullReferenceException("Full path" + 
                      " not found for the selected item");
        }
    }

ExecuteCommand

This command is used to launch the application corresponding to the selected project as if you double click on the ".exe" file in the 'Windows Explorer'. To do it, I call the Process.Start with the name of the assembly as parameter:

C#
System.Diagnostics.Process.Start(assemblyPath);

The assembly path is found by using the following code:

C#
private string GetAssemblyPath(EnvDTE.Project project)
{
    Property outputPath = 
      project.ConfigurationManager.ActiveConfiguration.
      Properties.Item("OutputPath");
    Property assemblyName = project.Properties.Item("OutputFileName");
    return GetFolderPath(project.FullName) + "\\" + 
      (string)outputPath.Value + (string)assemblyName.Value;
}

CollapseCommand

This command is used to collapse al the nodes of the Solution Explorer window. To do it, I search (recursively) for all child nodes (of the root node) and then loop on to set their 'Expanded' property to false using the following code:

C#
private void Collapse(UIHierarchyItem item, ref UIHierarchy solutionExplorer)
{            
    foreach (UIHierarchyItem innerItem in item.UIHierarchyItems)
    {                
        if (innerItem.UIHierarchyItems.Count > 0)                
        {                    
            // Recursive call                    
            Collapse(innerItem, ref solutionExplorer);

            // Collapse                    
            if (innerItem.UIHierarchyItems.Expanded)
            {                        
                innerItem.UIHierarchyItems.Expanded = false;
                if (innerItem.UIHierarchyItems.Expanded)                        
                {                            
                    // Bug in VS 2005                            
                    innerItem.Select(vsUISelectionType.vsUISelectionTypeSelect);      
                    solutionExplorer.DoDefaultAction();   
                }
            }
        }
    }
}

SearchHelpOnWebCommand

This command is used to search help for the currently selected source code on web sites which are defined in the 'SearchEngineEurls.xml' file. For each SearchEngineUrl you define in this file, a menu item is added to the 'Search help' menu (see image at the top of this article). As you can see below, by default, the 'Search help' menu will contain two menu items called 'Google' and 'MSDN', but you can define as many entries as you want.

XML
<?xml version="1.0" encoding="utf-8"?>
<SearchEngineUrlsFile 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SearchEngineUrls>
    <SearchEngineUrl Name="Google" 
       Url="www.google.fr/search?q=" />
    <SearchEngineUrl Name="Msdn" 
       Url="http://search.microsoft.com/search/
            results.aspx?view=msdn&q="/>
  </SearchEngineUrls>
</SearchEngineUrlsFile>

To do it, I get the current 'Selection' using the following code :

C#
selection = ((TextSelection)Application.DTE.ActiveWindow.Selection)

If no text is selected, I programmatically select the nearest word of the cursor. Then, I concatenate the 'search engine URL' which corresponds to the selected menu item (MSDN or Google or ...) and the selected text => this gives me the complete search URL. Finally, I just open this URL in a new tab in the Visual Studio Environment like this :

C#
Application.DTE.ItemOperations.Navigate(
    SearchEngineUrl + HttpUtility.UrlEncode(selectedText),
    vsNavigateOptions.vsNavigateOptionsNewWindow);

Debug commands: LogCommandBarsCommand and LogItemPropertiesCommand

To develop this add-in, I had to:

  1. Find the CommandBars corresponding to the 'Solution', 'Project', 'Folder',... nodes to be able to add commands => LogCommandBarsCommand logs in the Log4Net file all the CommandBar names (and the associated commands).
  2. Find the properties of the selected item to retrieve the full path of the 'Web project', for example => LogItemPropertiesCommand logs in the Log4Net file, the name and value of all properties of the selected item.

Log4Net

Log4Net is a port of the excellent Log4J logging framework (see this website for more explanations). Here, I use it to log in a file all the commands selection by the user. To do it, I configure Log4Net in the app.config file like this:

XML
<log4net>
  <!-- Define level and appender to use for root logger -->
  <root>
    <level value="ALL" /> <!-- can be one of the following : 
                           ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF -->
    <appender-ref ref="FileAppender" />
  </root>

  <!-- Define appender -->
  <appender name="FileAppender" type="log4net.Appender.FileAppender">
    <param name="File" value="C:\ExplorerAddin.log.txt" />
    <param name="AppendToFile" value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
    </layout>
  </appender>
</log4net>
Then, I only have to declare a logger:
C#
protected static readonly ILog _logger = 
  LogManager.GetLogger((MethodBase.GetCurrentMethod().DeclaringType));

and use it:

C#
_logger.DebugFormat("Starting to open " + 
          "the following folder : '{0}'", folderPath);

History

  • 2008/06/16
    • Altered CollapseItems method
    • Updated source and add-in
  • 2006/12/28
    • Added the 'SearchHelpOnWebSite' command.
    • Refactored the menus creation and the CommandBase class.
  • 2006/12/10
    • The 'Collapse' command collapses all nodes (and not only the top level nodes)
  • 2006/12/06
    • Added the 'Collapse' command.
    • Modified the 'OpenFolder' command to be able to do it on a 'Web project folder' and to open a folder with another file manager than 'Windows Explorer'.
    • Added the use of the Log4Net framework to log all actions.
  • 2006/11/20
    • Modification of the structure of the add-in.
    • Added details to the article.
  • 2006/10/26
    • First version.

Conclusion

I hope you will enjoy this add-in.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
France France
Software developer for Capgemini company.

Comments and Discussions

 
GeneralThanks Pin
danasegaranea9-Dec-08 20:08
danasegaranea9-Dec-08 20:08 
QuestionIs it for VS 2008? Pin
Xia Zheng Xin6-Dec-08 3:16
Xia Zheng Xin6-Dec-08 3:16 
AnswerRe: Is it for VS 2008? Pin
Sylvain BLANCHARD22-Dec-08 19:33
Sylvain BLANCHARD22-Dec-08 19:33 
QuestionCan't see the changes I made when I am not Debugging Pin
sooyang park30-Oct-08 15:22
sooyang park30-Oct-08 15:22 
AnswerRe: Can't see the changes I made when I am not Debugging Pin
Sylvain BLANCHARD22-Dec-08 19:42
Sylvain BLANCHARD22-Dec-08 19:42 
GeneralCool Addin! Pin
Brian C Hart27-Aug-08 5:30
professionalBrian C Hart27-Aug-08 5:30 
GeneralThanks Pin
chitzosu12-Aug-08 10:59
chitzosu12-Aug-08 10:59 
QuestionHow to add explorer nodes to testView window Pin
Nikola Milosevic25-Jul-08 6:19
Nikola Milosevic25-Jul-08 6:19 
GeneralAlternate method. Pin
Surendra Sambana16-Jun-08 8:01
Surendra Sambana16-Jun-08 8:01 
GeneralRe: Alternate method. Pin
SoTTo30-Jun-08 2:23
SoTTo30-Jun-08 2:23 
GeneralInstalling the Add-in for Visual Studio 2008 Pin
Blue Tangerine10-Jun-08 8:51
Blue Tangerine10-Jun-08 8:51 
GeneralRe: Installing the Add-in for Visual Studio 2008 Pin
Sylvain BLANCHARD14-Jun-08 23:42
Sylvain BLANCHARD14-Jun-08 23:42 
GeneralRe: Installing the Add-in for Visual Studio 2008 Pin
datacore16-Sep-08 4:19
datacore16-Sep-08 4:19 
GeneralBug fix for collapsing with solution folders Pin
chris from bluedevilsoftware4-Jun-08 6:01
chris from bluedevilsoftware4-Jun-08 6:01 
GeneralRe: Bug fix for collapsing with solution folders Pin
Sylvain BLANCHARD14-Jun-08 23:39
Sylvain BLANCHARD14-Jun-08 23:39 
GeneralMerci! Pin
alandraper29-May-08 13:28
alandraper29-May-08 13:28 
QuestionHow to get the menu at the file level ? Pin
Sreenath Madyastha21-Feb-08 10:25
Sreenath Madyastha21-Feb-08 10:25 
AnswerRe: How to get the menu at the file level ? Pin
Sylvain BLANCHARD23-Mar-08 0:25
Sylvain BLANCHARD23-Mar-08 0:25 
GeneralRe: How to get the menu at the file level ? Pin
Prasant Kumar Rout24-May-08 20:17
Prasant Kumar Rout24-May-08 20:17 
QuestionIssue with projects under solution. Pin
Naveed Kharadi14-Dec-07 10:32
professionalNaveed Kharadi14-Dec-07 10:32 
AnswerRe: What is the code license ? Pin
Sylvain BLANCHARD20-Oct-07 20:41
Sylvain BLANCHARD20-Oct-07 20:41 
GeneralRe: What is the code license ? Pin
jcoffman5-Nov-07 6:29
jcoffman5-Nov-07 6:29 
GeneralCareful when editing the SearchEngineUrls! Pin
tommy skaue9-Oct-07 22:27
tommy skaue9-Oct-07 22:27 
GeneralRe: Careful when editing the SearchEngineUrls! Pin
Sylvain BLANCHARD14-Oct-07 1:02
Sylvain BLANCHARD14-Oct-07 1:02 
GeneralRe: Careful when editing the SearchEngineUrls! Pin
tommy skaue14-Oct-07 12:48
tommy skaue14-Oct-07 12:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.