Friday, March 18, 2011

Automatic Upgrade from .NET 2 to .NET 3.5

Our core application suite is currently based on .NET 2, C# 2, VS2005, with a few dependencies on libraries from 3.0 and 3.5. I decided to perform a trial upgrade of the solution into VS2010, as I am using it for all new work and hate to revert back to 2005.

To start, I simply created a branch of the source, and then loaded the solution into VS2010. I waited for some time, and then eventually the import wizard completed – the result was a set of fully loaded .NET 2.0 projects within VS2010 – That seemed too easy! Of course, getting everything to compile was a different story. As stated above, several of the projects had taken some dependencies on 3.0 libraries – specifically WCF and WPF, and these projects longer compiled. Unfortunately they represented some core libraries within our project suit so this meant the solution was broken.

Instead of spending too much time finding out why, I converted these projects to the 3.5 framework via the project properties dialog and proceeded to compile – it soon became apparent however that I would be better off upgrading all projects in the same way, yet I didn’t have the time to upgrade 120 projects within the solution via the properties window..

Of course I knew that there had to be a better way, and having read about other attempts to do the same, II decided to write a macro to do the upgrade. Avner Kashtan provided a method here to process the projects within the solution like this:

For Each proj As Project In DTE.Solution.Projects

   Try

       proj.Properties.Item("TargetFramework").Value = 196613

       Debug.Print("Upgraded {0} to 3.5", proj.Name)

   Catch ex As Exception

       Debug.Print("Failed to upgrade {0} to 3.5", proj.Name)

   End Try

Next proj



I tried this but it didn’t do much – it turns out that Solution.Projects returns only the child nodes of the solution, which from my solution was simply 7 solution folders – so this didn’t work. Of course, I realised that I could rewrite this macro to be recursive so that I could traverse the hierarchy and process it that way.

This is what I came up with:

Sub Upgrade()
    For Each project As EnvDTE.Project In DTE.Solution.Projects
        UpgradeProject(project)
    Next
End Sub
 
Sub UpgradeProject(ByVal Project)
    For Each projectItem As EnvDTE.ProjectItem In Project.ProjectItems
        Dim childProject = TryCast(projectItem.Object, EnvDTE.Project)
        If childProject IsNot Nothing Then
            UpgradeProject(childProject)
        End If
    Next
 
    If Project.Kind = PrjKind.prjKindCSharpProject Then
        Project.Properties.Item("TargetFramework").Value = 196613
    End If
End Sub


This macro ran reasonably quickly and did the upgrade with the visible effect of changing all the project files to refer to the new framework version.

I then recompiled everything successfully.

Nice!