Friday, July 9, 2010

Visual Studio 2010 and CruiseControl.NET

Recently we upgraded from Visual Studio 2008 to 2010, which impacted our continuous integration and automated build process.  For continuous integration we're using CruiseControl.NET.  At the beginning of our Visual Studio 2010 upgrade we decided not to install Visual Studio 2010 on our continuous integration server.  Because CCNET is basically just running an MSBuild script, I figured all I needed was .NET 4.0 framework installed which would be a quicker, easier, cleaner (and more best practice-y) than installing the full Visual Studio 2010.  Well it didn't quite turn out to be that way and I eventually just ended up installing Visual Studio 2010 on the box.

Here are my reasons:

After converting my solution and project files, and then modifying the CCNET config to use the .NET 4.0 version of MSBuild instead of .NET 3.5, the first build attempt barfed with a bunch of errors like this:

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (1835,9): errorMSB3454: Tracker.exe is required to correctly incrementally generate resources in some circumstances, such as when building on a 64-bit OS using 32-bit MSBuild. This build requires Tracker.exe, but it could not be found. The task is looking for Tracker.exe beneath the InstallationFolder value of the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A. To solve the problem, either: 1) Install the Microsoft Windows SDK v7.0A or later. 2) Install Microsoft Visual Studio 2010. 3) Manually set the above registry key to the correct location. Alternatively, you can turn off incremental resource generation by setting the "TrackFileAccess" property to "false".

From this error I gleaned the fact that apparently, in addition to the .NET 4.0 framework, I also need the Windows 7.0A SDK.  Installing the SDK still seemed marginally better than installing full blown Visual Studio 2010, so I hunted around for it. I couldn’t find a download for the Windows SDK v7.0A anywhere on Microsoft sites, but I was able to find SDK 7.0.  It wasn’t obvious which download was compatible with Windows 2003 x64, but I eventually found one that would install.  After the install, I re-ran the build, and voila, same exact exceptions.

Ahh, but my failure was obvious.  You see, the error message was telling me that I need Windows SDK v7.0A (which Visual Studio 2010 installs) but the stand alone Windows SDK is v7.0.  My next step was to take a look at the registry key it was complaining about.  Low and behold there were v7.0 entries but no 7.0A entries.  The v7.0 entries looked simple enough, so I had the cringe worthy idea of exporting them, renaming v7.0 to v7.0a and then re-importing them, effectively creating copies of the registry keys to trick CCNET and MSBuild .   I probably should've stopped at this point but figured I was too close, and this one hack would probably do the trick. Alas, the third build yielded this beauty. 

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (1917,9): errorMSB3086: Task could not find "LC.exe" using the SdkToolsPath "" or the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A". Make sure the SdkToolsPath is set and the tool exists in the correct processor specific location under the SdkToolsPath and that the Microsoft Windows SDK is installed
The specified task executable location "C:\Program Files (x86)\MSBuild\Microsoft\WebDeployment\v10.0\aspnet_merge.exe" is invalid
C:\Program Files (x86)\MSBuild\Microsoft\WebDeployment\v10.0\Microsoft.WebDeployment.targets (1675,5): errorMSB4036: The "CollectFilesinFolder" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319" directory.
"nunit-console.exe" exited with code 30.

At this point I gave up, even though I suspect a few more hacks would’ve allowed my to run CCNET without Visual Studio, but quicker, easier and cleaner it certainly was not.