I have a long running tooling project that creates packages for multiple versions of visual studio (2005/2008/2010/2012/2013). The .csproj files (of which there are dozens) are all heavily macroized using an external targets files that gets the right references,
framework version, etc. based on environment variable settings. Although I'm required to have a separate solution file per project for each VS version [these are small files and only the version information at the top changes], I've managed to keep all of
the project files loading in all visual studio versions without VS either telling me the files aren't recognized or trying to upgrade them.
The fly in the ointment has been the ToolsVersion attribute, which cannot be macroized due to its placement on the root element of the project file. I always use toolsversion:#.# for command line builds with msbuild, but AFAIK VS doesn't have a similar setting.
I've just been setting this attribute to the latest version as new ones roll out: the earlier VS versions have been ignoring unrecognized tools and reverting to their default tool set, and the latest VS version doesn't try to upgrade my project when I open
the file.
This worked great until the switch to ToolsVersion="12.0". VS2013 tries to upgrade my projects for any earlier version (the project files were all previously 4.0), but VS2008 refuses to load them at all with this ToolsVersion. After some reading
and experimentation, I discovered that VS doesn't care about the number of the ToolsVersion attribute, but rather about what it points to in the registry.
Given that none of the official ToolsVersion numbers work with all of the VS versions I created a fake version instead. The project files now have ToolsVersion="12.34", and I have a small batch file that copies the full contents of 2.0/3.5/4.0/12.0
keys under HKLM\SOFTWARE[\Wow6432Node]\Microsoft\MSBuild\ToolsVersions into the 12.34 key in the same location. I now run my little batch file before opening the projects in a given version of VS (look at the VSVer.bat file in the trunk directory at orm.sf.net
if you're curious).
Obviously, this feels like a total hack, but desperate times call for desperate measures. Building the older versions from the latest VS incarnation is not a viable option because I have multiple academic teams that build this project: I can't control which
VS version is in use, and I can't make them install specific/multiple/all versions. One project file per VS version is also not a realistic option due the explosion in maintenance costs. Dynamically changing the project files before opening is also not realistic
because of the source control implications. Basically, any solution that doesn't allow the same project file to open unmodified in all of the VS versions is unacceptable.
Question:
- I'm curious what others have done in this situation.
- Is there any other more official way, or should I continue with this approach?
- Can I macroize this information in some property group? This would need to work for all of the VS versions.
- Is there some hidden VS command line option or setting that does the same thing astoolsversion for MSBuild?
Thanks,
-Matt