How to: Retarget a project using DTE

How to: Retarget a project using DTE

  • Comments 1

The upcoming .NET Framework 4 and Visual Studio 2010 (now in RC) has a lot of exciting new features. From BigInt and parallel libraries, to code contracts, CLR side by side, a new project system for C++ and multi-targeting. Just to name a few. There is much more. No matter what features you are the most interested in, you can start exploring.

Conversion and retargeting

If you have a Whidbey or Orcas project and try opening it in Visual Studio 2010, the conversion wizard will do all the necessary steps to make sure your project is usable in the new installment. You can start by opening your project in Visual Studio 2010:

The conversion wizard will popup and it will guide you step by step until the conversion is complete. When the conversion is done, the project will be loaded in Visual Studio. The conversion wizard may also ask you to retarget the project to .NET Framework 4, if you don't have the version of the framework your project is targeting installed.

After your project is loaded, you can then retarget to .NET Framework 4 or other version, from the project properties:

Project retargeting is a quite complex procedure, and goes beyond modifying the project file:

A retarget also unloads the project, may update the web.config and the app.config files (generating the latter if not on the disk), in the end to reload the project back in Visual Studio. That is why it can't always be done by externally modifying the project file.

TFMs and Client Profiles

In the project file sample above, the 2 properties identify which version of the framework, and optionally the profile, a project is targeting. They are not a target framework moniker (TFM) but they are rendered from one. A TFM is an identifier which tells the framework family, the version and the profile. It is used extensively by Visual Studio, and some of the higher level consumers are:

  • intellisense, to tell which types are available at runtime
  • Add Reference dialog, which assemblies should be displayed to the user
  • Toolbox, which controls to show
  • MSBUILD, which references to pass to the compiler 

A TFM may also denote a profile of a full framework. Technically a profile is no different from a full framework. There is a deployment package which delivers it, assemblies which it comes with and a user can reference, and you can target the profile from the project property pages. The difference lies on what's available for you to reference, that is why it is sometimes called a "subset". Not all the assemblies available in the full framework are available in one of its profiles. As an example, System.Web is not in the .NET Framework 4 Client Profile:

 

Profiles were designed to decrease the deployment cost and to allow users to extend an existing framework for particular needs. For example one can introduce a "Mono" profile and target it seamlessly in Visual Studio, or other popular Mono IDEs. A profile is also the default target for many project templates in Visual Studio 2010.

DTE retargeting

Say you have a bunch of projects in a solution, which were originally created in Orcas, and you want them to target .NET Framework 4. Is there an easy way other than manually going to the property pages and do it from the UI? With the new release of Visual Studio we are introducing a new DTE property which allows retargeting a project based on a TFM:

project.Properties.Item("TargetFrameworkMoniker").Value = ".NETFramework,Version=v4.0,Profile=Client";

Assuming you have an existing project and already acquired a DTE instance, this code will load the project in Visual Studio 2010 then retarget it to .NET Framework 4 Client Profile:            

// open an existing project
dte.Solution.Open(@"D:\Users\...\Projects\ConsoleApplication2\ConsoleApplication2.sln");                         

// assumes the first item in the collection is the target project
Project project = dte.Solution.Projects.Item(1);           

// retarget the project to .NET Framework 4 Client Profile
project.Properties.Item("TargetFrameworkMoniker").Value = new FrameworkName(".NETFramework", new Version(4, 0), Client").FullName;

You can then integrate this further in an add-in or a macro, to fulfill your special purposes. In Visual Studio 2010, go to Tools – Macros – Macros IDE. In the Project Explorer expand My Macros and in Module1 add this code:

' macro to retarget all C#/VB projects in a solution to .NET Framework 4
Sub SwitchFramework()
    Dim v40FrameworkName As FrameworkName = New FrameworkName(".NETFramework", New Version(4, 0))

    For Each project As EnvDTE.Project In DTE.Solution.Projects
       
If project.Kind = PrjKind.prjKindCSharpProject OrElse 
           
project.Kind = PrjKind.prjKindVBProject Then 

           project.Properties.Item("TargetFrameworkMoniker").Value = v40FrameworkName.FullName
       
End If 
    Next
End Sub

This will retarget all C# and VB projects from your solution to .NET Framework 4.

I hope that you find this post useful, and let us know if you have any questions.

  clip_image001

Ion Todirel, Visual Studio: Project and Build

"Hi, I’m Ion and you may know me from Channel 9. I’m a test dev in the Project and Build team. I work mainly on multitargeting, references and other design-time features."

Leave a Comment
  • Please add 5 and 7 and type the answer here:
  • Post
  • Thanks for posting this macro - it was very useful. I had to tweak it slightly for my usage because I use solution folders a lot:

    Const projectFolder = "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}"

       ' macro to retarget all C#/VB projects in a solution to .NET Framework 4

       Sub SwitchFramework()

           Dim v40FrameworkName As FrameworkName = New FrameworkName(".NETFramework", New Version(4, 0))

           For Each project As EnvDTE.Project In DTE.Solution.Projects

               SwitchFramework_Project(project, v40FrameworkName)

           Next

       End Sub

       Sub SwitchFramework_Project(ByVal project As EnvDTE.Project, ByVal targetFramework As FrameworkName)

           If project.Kind = projectFolder Then

               ' Recurse

               For Each projectItem As EnvDTE.ProjectItem In project.ProjectItems

                   Dim childProject = TryCast(projectItem.Object, EnvDTE.Project)

                   If childProject IsNot Nothing Then

                       SwitchFramework_Project(childProject, targetFramework)

                   End If

               Next

           ElseIf project.Kind = PrjKind.prjKindCSharpProject OrElse project.Kind = PrjKind.prjKindVBProject Then

               ' Switch the TFM

               project.Properties.Item("TargetFrameworkMoniker").Value = targetFramework.FullName

           End If

       End Sub

Page 1 of 1 (1 items)