Last week I posted up on how we had figured out a way of building .NET 2.0 code developed in Visual Studio 2008 under Team Build 2005 (a component of Team Foundation Server 2005). That post received quite a bit of traffic but like a lot of people I was disappointed that I couldn’t get build .NET 3.5 code, especially since some of our own internal users were asking questions about it.
This week I asked Grant Holliday to prepare a custom .NET 3.5 build server and plug it into Readify’s own TFS Now instance. My mission was clear – get our own internal .NET 3.5 projects building on top of the TFS Now infrastructure using Visual Studio 2008, Team Build 2005 and a cup of coffee.
Mission Accomplished!
I’m pleased to say that we managed to get to the bottom of this one with a fairly satisfactory solution. One of the things that I had to overcome was the fact that Team Build 2005 is hardwired to use the version of MSBuild that shipped with the .NET 2.0 runtime and unfortunately, Visual Studio 2008 projects that target the .NET 3.5 runtime must use the version of MSBuild that ships with the .NET 3.5 runtime.
As I was thinking about the problem I realized that since we already had a working .NET 2.0 build server, I would be able to dedicate this new build server to building .NET 3.5 code, so with a little bit of creative coding (and *.exe file replacement) I could make Team Build 2005 think it was calling MSBuild from .NET 2.0, but in reality, just forward that request to MSBuild from .NET 3.5.
What I needed to do was create a program called MSBuild.exe which I could drop in on top of the .NET 2.0 version of MSBuild that simply took the arguments passed to it and call the .NET 3.5 version of MSBuild. It ended up being about 25 lines of code in a single mainline.
After dropping the executable (MSBuild.exe) compiled from the code into the “C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727″ directory you will effectively be using .NET 3.5 to do all of your builds. My recommendation is to create a separate build server for this task so that you still have a clean .NET 2.0 build environment.
In the end this ended up being much simpler than I expected, and it seems to work perfecting, including updating the Team Foundation Server 2005 build store. If you have a build server you can use for this purpose you can avoid using the more involved Team Build trick that I posted about earlier.

35 comments
Comments feed for this article
September 1, 2007 at 3:37 pm
Jason
Hi,
Nice solution. I remember playing the old switch-the-exe-file for doing complex builds in VB6 days. It would nice if it were possible to change where Team Build looks to find MSBuild so you don’t have to mess with the files in the Windows folder.
Have you considered getting your replacement msbuild.exe stub to parse the arguments, open the solution/project file and determine from that whether to relay the call to the 2.0 or 3.5 version of MSBuild?
This could remove the need to maintain two build servers.
September 2, 2007 at 10:23 am
My VSTS Blog : Building .NET 3.5 Applications with Team Build 2005
[...] he has managed to work out how to get Team Build 2005 building .NET 3.5 applications. Mitch has posted this now on the TFS Now blog. Well worth a look if this is something you are needing to do. I’m keen to [...]
September 2, 2007 at 11:41 am
Mitch Denny
Hi Jason,
I had considered that. What I would need to do is read the TFSBuild.proj file to get a pointer to the solution file. Since the solution isn’t downloaded until after TFSBuild.proj is executed though it makes it a litle bit tricky to intercept at that level.
VS2005 projects will probably build OK under MSBuild 3.5 though.
October 22, 2007 at 9:02 pm
TFS2008: Restrict Target Framework Version task « Grant Holliday
[...] This is great news. It means that you can start using Team Build 2008 and/or Visual Studio 2008 to build existing solutions that target the .NET 2.0 runtime. This gives you the flexibility to upgrade to .NET 3.5 when your development cycle allows. (As a side note, if you want to build .NET 3.5 applications with Team Build 2005, this should help) [...]
October 22, 2007 at 9:30 pm
VSTS 2005 / 2008 Compatibility Matrix « Grant Holliday
[...] TFS Now – Building .NET 3.5 Applications with Team Build 2005 [...]
November 22, 2007 at 8:12 pm
Darin
Hi, nice solution. I had problems with the quoted arguments so I used instead:
string arguments = Environment.CommandLine.Replace(
@”"”C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\msbuild.exe”"”,
string.Empty);
Process process = Process.Start(
@”c:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe”,
arguments
);
November 30, 2007 at 3:07 am
Buck Hodges : Building VS 2008 projects with TFS 2005
[...] Building .NET 3.5 Applications with Team Build 2005 [...]
November 30, 2007 at 3:39 am
Building VS 2008 projects with TFS 2005 - Noticias externas
[...] Building .NET 3.5 Applications with Team Build 2005 [...]
November 30, 2007 at 4:09 am
MSDN Blog Postings » Building VS 2008 projects with TFS 2005
[...] The best workaround that I’ve seen is to create a “shim” msbuild.exe in the .NET 2.0 directory that invokes the msbuild.exe in the .NET 3.5 directory. Mitch Denny posted this approach and the code to go along with it. Building .NET 3.5 Applications with Team Build 2005 [...]
November 30, 2007 at 4:19 am
Steven Perry
This worked great! Thanks.
November 30, 2007 at 7:49 pm
Tim
I wanted to use VS2008 with TFS2005 but still build to .NET 2
You workaround did not work for me.
December 4, 2007 at 1:41 am
Charles Teague
I want to use this method, but can you help me out with the steps? I’ve already got TeamBuild2005 installed on an OS that I’ve been using for awhile, and our TFS2005 will not be upgraded until Q1′08 time-frame. I’ve converted our 2005 solutions to 2008, but now need to enable the TeamBuild as you’ve mentioned here.
Do I perform a side-by-side installation of TeamBuild2008 on the same build server I already have TeamBuild 2005 on? If so, what do I do about the port conflice dialog at the beginning of the installation?
December 11, 2007 at 1:41 pm
GK
Or you can just edit your proj file and replace ference to 2.0 framework with 3.5 and your done. Worked like a charm for me.
Gk
December 12, 2007 at 5:41 am
Alek
Hi,
?
your solution works great for building, but then the build fails on running Unit Tests – it does not understand vsdmi file saved in VS 2008.
Do you have any solution for that issue too
December 13, 2007 at 10:07 am
Mitch Denny
Hi Tim,
What error are you seeing.
December 13, 2007 at 10:24 am
Mitch Denny
Hi Charles,
You don’t need to install Team Build 2008. You just need to apply the MSBuild.exe hack that I have outlined.
December 13, 2007 at 10:24 am
Mitch Denny
Hi GK,
Did you not have problems with the VS2008 solution file format and MSBuild 1.0 not being able to process it?
December 13, 2007 at 10:25 am
Mitch Denny
Hi Alek,
Yes, sadly unit testing is a problem I haven’t solved yet, but since TFS2008 is now out I’m probably not going to spend too much time on it.
December 14, 2007 at 11:27 pm
Tim
Mitch,
If I run the modified MSBuild in the framework v2 folder everything works. However, if I then try the build from within TFS it fails with no explanation or log files created
December 15, 2007 at 1:18 am
Valery
I dropped this fake MSBuild.exe and I have now the following error.
Target InitializeEndToEndIteration:
C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\TeamBuild\Microsoft.TeamFoundation.Build.targets(165,5): error MSB4062: The “Microsoft.TeamFoundation.Build.UpdateBuildNumberDropLocation” task could not be loaded from the assembly \..\..\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll. Could not load file or assembly ‘file:///c:\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll’ or one of its dependencies. The system cannot find the file specified. Confirm that the declaration is correct, and that the assembly and all its dependencies are available.
There is a problem with the path as clearly Common7 is available but located in “C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies” on my Server…
What must be done to let the MSBuild find the correct path.
Notice : The build is running fine while using the actual MSBuild.exe 2.0
December 15, 2007 at 1:34 am
Valery
Since I have dropped this fake MSBuild instead of the v2.0, I get the following error :
Target InitializeEndToEndIteration:
C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\TeamBuild\Microsoft.TeamFoundation.Build.targets(165,5): error MSB4062: The “Microsoft.TeamFoundation.Build.UpdateBuildNumberDropLocation” task could not be loaded from the assembly \..\..\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll. Could not load file or assembly ‘file:///c:\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll’ or one of its dependencies. The system cannot find the file specified. Confirm that the declaration is correct, and that the assembly and all its dependencies are available.
Clearly, this is not the right location. Is there an explanation why the relative path does not match with “C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies” ?
Notice : our Build Server has been installed and configured by a Microsoft Consultant. It’s using a “SofwareFactory.Build.Tasks” among other to manage the versioning. I have to say that I ignore everything about this “addon”. It’s “imported” in our Build Scripts:
Do you now this “quite standard” addon and could it be responsible for our issue ?
December 26, 2007 at 11:10 am
Mitch Denny
Hi Tim,
Can you give me some details about your source code structure and the definition of the team build type?
December 26, 2007 at 11:12 am
Mitch Denny
Hi Valery,
Something doesn’t seem quite right in your environment. Can you try a clean bulid server and just try building a simple console application?
January 4, 2008 at 8:31 pm
Valery
As this server was installed by a Microsoft Consultant, we will contact him again and ask for additional explanations on what is done exactly by its “Software Factory”. Currently, we only know that it is used to make the build process more flexible by generating custom build scripts for each project to be built…
January 12, 2008 at 4:14 pm
Barry
I’ve the same problem as Tim
I’ve replaced MSBuild.exe in 2.0 folder with my custom MSBuild, TeamBuild stopped without any logs and errors.
I tested my custom MSBuild in command line, it can redirect to 3.5 properly, arguments are also passed successfully. However, it does not work under TeamBuild.
January 22, 2008 at 8:05 pm
Andre
Hi Mitch,
I read you solution and I think that this is the same issue within my environment. I had some problems with the /p: arguments, which where treated wrongly. So I changed your code snippet. Here is my solution:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2656654&SiteID=1
cheers,
Andre
January 24, 2008 at 11:30 pm
Mitch Denny
Hi guys,
I’d recommend moving to TFS 2008 now, this was just an interim hack.
April 4, 2008 at 2:39 am
oo
Thanks.
I’ve developed your idea further – my version of the tool reads TFSBuild.rsp and looks for the MSBuildCommandPath property. If present, the specified command gets called, otherwise the call is handed over to MSBuild-org.exe
TFSBuild.rsp
—————
/property:MSBuildCommandPath=C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe
This greatly eases our migration path to TFS2008. Cheers,
Olivier
April 15, 2008 at 1:51 am
Tommy Norman
Mitch,
I am consulting for a client where we need to build 3.5 projects on their TFS 2005 server, but they are uncomfortable changing the MSBuild executable. I was going to look into just shelling out to DEVENV and compiling the 3.5 projects from the command line (like you do for building setup projects). I was even contemplating writing a custom build taks to do it that could then take the output and write it to the build log. Before I started I wanted to see if this was way offbase or if you think it acutally might work.
regard,
Tommy
April 26, 2008 at 7:09 am
Mitch Denny
At this point I’d recommend upgrading to TFS 2008 as the best course of action.
June 3, 2008 at 7:30 am
Vanitha
Barry/Tim,
Do you have a resolution to the issue that you are facing regarding getting the builds to run within Team Build? I am facing the same issue now, while the redirection to MSBuild 3.5 works as expected, there seems to be an error and Team Build does not provide any logs for me to determine what might be the issue. My Team Build type was created using VS 2005. Could this be an issue? The same build type works fine using MSBuild 2.0. I appreciate your inputs!
Thanks!
July 19, 2008 at 4:23 am
Wassup Jose » Blog Archive » TFS 2005 Build Server building 2008 Solutions
[...] thanks for making 2008 solutions build seamlessly in TFS2005! I had completely forgotten that a workaround was needed to build 2008 solutions in 2005 msbuild. However, you owe me a fucking apology for [...]
September 19, 2008 at 6:58 pm
Jonathan Dickinson
I just put up a ‘more complete’ shim on my blog. It allows you to shim any file (via registry settings) and also supports the standard in, out and error streams, as well as the ctrl+c sequence. This should allow the MSTest.exe file to be shimmed as well (but I am still installing TFS 2005, so this isn’t confirmed).
http://geekswithblogs.net/jcdickinson/archive/2008/09/18/tfs-build-server-2005-with-2008-solutions.aspx
November 18, 2008 at 4:56 am
Paul
I feel a little silly, but I was trying to build your MSBuild.exe with your 25 lines of code so graciously provided. But since I am a web developer and not an application developer I’m not sure what type of Visual Studio Project I am supposed to use to create an .exe and I keep getting an error on the process.WaitForExit line, is there some type of using statement or reference that I am supposed to apply to this class?
Thanks so much for your help with this. The idea sounds great, I just need to actually create or get a copy of this .exe
November 18, 2008 at 5:56 am
Paul
oh never mind, I figured it out, it should be a “Web Application” project and change the output to .exe here is the fuller code I used (the middle part is same as yours), this might have an EXTRA using statement or two, but it does work (and works great I must say):
using System;
using Microsoft.CSharp;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading;
using System.IO;
namespace MSBuild
{
class Program
{
public static int Main(string[] args)
{
for (int argIndex=0; argIndex<args.Length;argIndex++)
{
if (args[argIndex].Contains(” “))
{
string quotedArg= string.Format(“\”{0}\”", args[argIndex]);
args[argIndex]=quotedArg;
}
}
string arguments = string.Join(” “,args);
Process process = Process.Start(“C:\\WINDOWS\\Microsoft.NET\\Framework\\v3.5\\MSBuild.exe”,arguments);
process.WaitForExit();
return process.ExitCode;
}
}
}