Gary Joynes
Gary Joynes

Reputation: 656

Updating Visual Studio project references programmatically

I wish to programmatically update the references in the projects in my Visual Studio solution.

I have roughly 15 projects in my solution and when I am developing/debugging I want the references to point to the projects within the solution.

As part of my release procedure I sometimes need to make a copy of one project and then update the references to point to built dlls in a certain folder.

I can work out the structure of the project files and how references work within them and I am thinking of building a command line tool to parse the project files and change references as required.

My questions are:
1. Does this sound a sensible thing to do
2. Has anyone experience of this and/or how do they handle switching between developing and release modes
3. Does anyone have any libraries that deal with parsing Visual Studio project files.

CLARIFICATION:

Thanks for the responses. Perhaps I should clarify a few situations where I wish to use this.

a) My application contain 15 projects. I try and keep the solution as small as possible for what I am working on, so say I have 5 projects in my solution. I now need to debug/develop one of the projects not in the solution so I add this project but I have to: - set the references in the original projects to point to project references rather than compiled dlls - change the references in the newly added project to point to the appropriate project references

I would like my tool to do this automatically and the only way I know to so this at present is manipulating the project files

b) As part of a service pack build procedure I take a copy of one of the projects, make the necessary code changes and build using Visual Studio. To do this I have to change all the references to the compiled dlls

Upvotes: 9

Views: 7670

Answers (6)

Tom Stephens
Tom Stephens

Reputation: 81

I don't think there is an easy answer to your first question. As a rule, I would recommend avoiding this situation. It's difficult to handle manually, and the code to manage it is not trivial.

That said, I have run into a situation at my job where I simply couldn't get around the problem. In our case, we were working to release an SDK which needed to include a set of sample projects. The "development" version of those projects used both project references as well as references to 3rd party libraries.

That brings us to #3 which is basically, yes. I have actually released an open source project with a library, a simple windows utility and a NAnt extension to automatically change project references to dll references. In fact, it also handles moving those 3rd party libraries to the same local folder and updates those references in the project file.

This solution isn't perfect and there are a lot of improvements I'd like the time to add, but it does work for our situation. Part of our release script which is all in NAnt runs this process to swap out all of the references to a relative path. Then we can easily bundle this whole setup. One day maybe I'll get the time to add an MSBuild Task along with the project.

Again, I think it is best to avoid this as much as possible, but if you get stuck like me - the code I released should at least help.

Upvotes: 1

Djabx
Djabx

Reputation: 745

There is tool on visual studio gallery that might help you.

It can replace references on your solution with projects when adding them and vice versa if removed.

https://visualstudiogallery.msdn.microsoft.com/056617a4-da39-4d7b-8ecf-933009d9b721

Upvotes: 0

mcintyre321
mcintyre321

Reputation: 13306

I think if you use the Microsoft.Build.BuildEngine library you can manipulate the projects programmatically after loading.

http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.aspx

Upvotes: 0

Terrance
Terrance

Reputation: 11862

Tiger, Tiger ROAR !!!

This is using the DTE and VSProject to programmatic add references. I commented the code for the majority of the explanation. But to add I did throw a ton of different extra references because i'm kinda lazy. But just sort with Visual Studio and you should be okay. If for any reason this doesn't compile feel free to yell at me.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using EnvDTE;
using EnvDTE80;
using EnvDTE90;
using EnvDTE90a;
using Extensibility;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Design;
using Microsoft.VisualStudio.Shell.Interop;
using VSLangProj;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            //Disclaimer: 
            //I am doing this through an extention, Getting 
            //a ref to DTE may not work quite the same for you as 
            //there are several different ways to do it. But the 
            //VSProject stuff shouldn't be an issue

            //Get your DTE Reference, I'm using DTE2 from EnvDTE80 
            //I hadn't dug into whats the earilest compatible version
            //The Package is Microsoft.VisualStudio.Shell.Package
            DTE2 _appObject = Package.GetGlobalService(typeof(DTE)) as DTE2;

            //This gets the first project in the solution set and casts it as a VSProject
            //Note that Web projects use a different type , Something like VSWebProject 
            //or something I forget...
            var pj = (VSProject)_appObject.Solution.Projects.Item(1).Object;

            //Your dll path
            pj.References.Add(@"c:\MyRefs\Pastry.dll");
        }
    }
}


Upvotes: 1

JaredPar
JaredPar

Reputation: 754545

I think a better approach to this would be to use Conditional blocks on your references inside the project file directly. Then all you need to do is set a particular flag during the msbuild for the "release" build and it will pick up the correct references.

For instance

<ItemGroup Condition="'$(IsRelease)'=='True'">
  <Reference Include="..." />
</ItemGroup>
<ItemGroup Condition="'$(IsRelease)'!='True'">
  <Reference Include="..." />
</ItemGroup>

Upvotes: 11

Steve Cooper
Steve Cooper

Reputation: 21470

Sounds like an odd situation.

My suggestion is this.

  1. Split off the projects that have prebuilt versions into a separate solution. Have them all build to

    \assemblies\fromsource

  2. Copy the prebuilt ones into;

    \assembly\prebuilt

  3. Before developing the rest of the projects, copy either directory into

    \assembly\development

  4. Change your projects to point to the versions in \assembly\development.

So now, you always build your product against precompiled binaries in a known folder, so you never need to change your project. But you can swap between versions at will.

For bonus points, change a prebuild event to copy the dlls across before things start building, and have the source folder vary based on configuration. Then add a PREBUILT configuration alongside DEBUG and RELEASE.

Upvotes: 0

Related Questions