Modifying a Visual C++ 2010 project’s Platform Toolset programmatically with IVCRulePropertyStorage

Back from a long hiatus.

Lately I’ve been migrating a large legacy code base from Visual C++ 2008 to Visual C++ 2010. Visual C++ 2010 supports Native Multi-Targeting, which lets you use the Visual Studio 2010 IDE and the new MSBuild-based C++ project system (*.vcxproj files, etc.) while invoking a legacy compiler like Visual C++ 2008 for the actual build, or for invoking the modern compiler with special INCLUDE and LIB directory settings (e.g., using the Windows Driver Kit’s headers and import libraries).

The “Platform Toolset” is the project setting which specifies which baseline compiler settings apply. Visual Studio 2010 bundles the “v100” platform toolset for using the Visual C++ 2010 compiler and the “v90” platform toolset for using the Visual C++ 2008 compiler. The Windows SDK 7.1 includes the “Windows7.1SDK” platform toolset which invokes the Visual C++ 2010 compiler, but with the SDK’s build environment. The latest Intel C++ Compiler includes a “Intel C++ Compiler XE 12.0” toolset, as well. A third party has even created a platform toolset for the antiquated Visual C++ 2003 compiler.

The IDE GUI exposes the Platform Toolset project setting in the General property sheet. By right clicking a project in Solution Explorer, clicking Properties and going to General under Configuration Properties, you can change the setting on a per-build configuration basis. Solution Explorer is clever enough to let you group select several or all of the projects in the open solution and group-modifying the platform toolset in the properties dialog. For many cases, this may be sufficient.

However, if you want to modify the platform toolset en masse, but based on more complicated criteria, or just wish to achieve a higher degree of automation in the migration process, you may prefer to modify the setting programmatically like I did.

Visual Studio has an automation model for modifying project settings and for many other IDE tasks. This object model is accessible from Visual Studio Macros (which have unfortunately been removed from the Visual Studio 11 Developer Preview) and from other forms of Visual Studio extensibility such as add-ins. After some browsing of the documentation and searching the Web, it is clear how to modify things like the project’s Linker OutputFile property. However, it took me a while to figure out how to access other properties like the PlatformToolset.

It turns out that project settings that have appeared recently are not accessible in straightforward way like the older ones. That is, they are not properties of the VCProject object or its child objects. Instead, there is a new interface for manipulating these properties, IVCRulePropertyStorage.

With this interface, the PlatformToolset property in the General property sheet becomes easily accessible. To illustrate, the following is an example Visual Studio macro that changes the platform toolset of any project in the solution using the “v100” toolset to the “Windows7.1SDK” toolset:

Option Strict On
Option Explicit On

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports Microsoft.VisualStudio.VCProject
Imports Microsoft.VisualStudio.VCProjectEngine

Public Module Module1
Sub RetargetProjects()
  For Each p As Project In DTE.Solution.Projects
    If p.Kind = vcContextGuids.vcContextGuidVCProject Then
      Dim prj As VCProject = CType(p.Object, VCProject)

      For Each cfg As VCConfiguration In CType(prj.Configurations, IVCCollection)
        Dim generalRule As IVCRulePropertyStorage = CType(cfg.Rules.Item("ConfigurationGeneral"), IVCRulePropertyStorage)

        Dim currentPlatformToolset = generalRule.GetUnevaluatedPropertyValue("PlatformToolset")

        If currentPlatformToolset = "v100" Then
          generalRule.SetPropertyValue("PlatformToolset", "Windows7.1SDK")
        End If
    End If
End Sub
End Module

You need to add references to the VCProject and VCProjectEngine assemblies in your macro project to access the types of the Visual C++ Project Model used in this macro.

Stay tuned for more useful functionality of IVCRulePropertyStorage.