Automating Visual Studio 2010 – Part 2 1


Continuing on from Part 1, our objective in this article is to create a new Visual Studio solution, and then populate it with some existing projects.  To facilitate this, it would be beneficial if you had a few projects already created.  For this example, I have defined the following structure:

C:\UnitTesting – Root Folder

C:\UnitTesting\TestSolution – An existing folder which contains subdirectories which hold project files.

The sample structure is as follows:

image

So basically, there are three projects and two reference each other.  Our goal is to create a new solution file in the root directory which is then populated with references to the existing project files.

Please bear in mind that this is all demo code, and lacks the normal hardening and checks which production code should have.  Please use wisely, as there are no refunds.. ha!

I’ve reworked the previous example to be a little more robust, as follows:

  1. Encapsulated the functionality to create a new blank solution file (a method called CreateSolution())
  2. Second, I’ve added a new function called AddProjects which will take a path, plus details about the target solution file.

I’ve moved the DTE2 object to be a static object, and refactored CreateSolution thus:

private static DTE2 _dte2 = (DTE2)Microsoft.VisualBasic.Interaction.CreateObject("VisualStudio.DTE.10.0", "");

public static void CreateSolution(string path, string solutionName)
{
    Solution4 solutionObject = (Solution4)_dte2.Solution;
    solutionObject.Create(path, solutionName);
    solutionObject.Close(true);
}

Unit testing for this was easy enough:

[TestMethod]
public void CreateEmptySolution()
{
    SolutionHelper.CreateSolution(@"C:\UnitTesting\", "UnitTestSolution");
}

[TestMethod]
public void AddProjects()
{
    File.Delete(@"C:\UnitTesting\UnitTestSolution.sln");
    SolutionHelper.AddProjects(@"C:\UnitTesting\UnitTestSolution.sln", @"C:\UnitTesting\TestSolution", "*.*proj");
}

As you can see, all pretty straightforward.  So reviewing our CreateSolution function, it now just takes a path and solution name (omit the “.sln” extension) and creates the empty solution.

The next step is to iterate and find projects, and finally – add them to a solution file.  I’ve added some logic which creates the target Solution File if it does not exist.

The AddProjects function is pretty easy to understand:

public static void AddProjects(string solutionFile, string projectPath, string projectWildCardMatch)
{
    if (!File.Exists(solutionFile))
    {
        CreateSolution(Path.GetDirectoryName(solutionFile), Path.GetFileName(solutionFile));
    }

    Solution4 solutionObject = (Solution4)_dte2.Solution;
    solutionObject.Open(solutionFile);

    var fileNames = Directory.GetFiles(projectPath, projectWildCardMatch, SearchOption.AllDirectories);

    foreach (string projectFile in fileNames)
    { 
        solutionObject.AddFromFile(projectFile, false);
    }

    solutionObject.Close(true);
}

Hopefully you can see how easy it is to add projects to the solution.  The boolean value in the call Solution.AddFromFile is important, as it elects to use the currently loaded solution.  If omitted, it is either attached to the project’s original solution (in my experience).  Make sure you save the solution when closing it.

If we open the generated solution file in Visual Studio 2010, you’ll see that not only are the projects added, but they also show the references:

image

Here is a complete copy of the source file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE80;
using EnvDTE100;
using System.IO;
using EnvDTE;
using System.Diagnostics;

namespace VSAutomation.Toolkit
{
    public static class SolutionHelper
    {
        private static DTE2 _dte2 = (DTE2)Microsoft.VisualBasic.Interaction.CreateObject("VisualStudio.DTE.10.0", "");

        public static void CreateSolution(string path, string solutionName)
        {
            Solution4 solutionObject = (Solution4)_dte2.Solution;
            solutionObject.Create(path, solutionName);
            solutionObject.Close(true);
        }

        public static void AddProjects(string solutionFile, string projectPath)
        {
            if (!File.Exists(solutionFile))
            {
                CreateSolution(Path.GetDirectoryName(solutionFile), Path.GetFileName(solutionFile));
            }

            Solution4 solutionObject = (Solution4)_dte2.Solution;
            solutionObject.Open(solutionFile);
            
            var fileNames = Directory.GetFiles(projectPath, "*.*proj", SearchOption.AllDirectories);

            foreach (string projectFile in fileNames)
            { 
                solutionObject.AddFromFile(projectFile, false);
            }

            solutionObject.Close(true);
        }
    }
}

About Rob Sanders

IT Professional and TOGAF 9 certified architect with nearly two decades of industry experience, 18 years in commercial software development and 11 years in IT consulting. Check out the "About Rob" page for more information.


Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

One thought on “Automating Visual Studio 2010 – Part 2

  • Farrukh

    Rob,
    Thanks a lot for such a useful tool. I was looking for something like this. Before, I was trying to use Powershell, but somehow, it was unable to get DTE object, so decided to write small utility application, and got the code from your tutorial…

    Really appreciated.

    Farrukh