Agafonov Slava Digest about software

MSBuild 4.0 and MSBuild 3.5 problems on TFS Continuous Integration server

Have you ever had problems with transformation your build server to new project configuration, new version of .NET Framework or MSBuild? If you answer yes and your configuration connected to TFS build server and MSBuild 3,5 or 4.0 than this article for you. Maybe you have mistakes MSB3644 or "MSB3245: Could not resolve this reference. Could not locate the assembly "RadDock.Net2". Check to make sure the assembly exists on disk. If this reference is required by your code, youmay get compilation errors." on you your build machine?

 

So what are these "reference assemblies", are why are they needed for compilation? First, let's look back at .NET 2.0 (which didn't have reference assemblies) so that we can understand the problem that Microsoft wanted to solve. In .NET 2.0, MSBuild tells the compilers to directly reference the assemblies from the Framework's directory. The problem was: when .NET 2.0 SP1 added new classes and members, developers could accidentally use the new classes and make their program incompatible with the unpatched .NET 2.0. In .NET 4.0, Microsoft solves this problem by separating the assemblies used for compilation from the assemblies used for runtime. When you install the .NET Framework, you only get the runtime assemblies (installed in the GAC). These may be patched by hotfixes or service packs. However, the patches will not touch the separately installed reference assemblies: the compiler will continue to check your code against the original .NET 4.0 API. In fact, if you try to open the reference assemblies in Reflector, you won't see any code: these assemblies have only the metadata and do not contain any IL instructions. They are intended as a API reference only.

But, while reference assemblies certainly are a good idea, not everybody has them installed. The ".NET 4.0 Targeting Pack" is not available as a standalone download, the only way to get it is to install the Windows SDK 7.1 (a 585 MB download) or to install Visual Studio 2010. So we decided that SharpDevelop 4.0 should be usable without having the reference assemblies installed. You won't get their benefits (when the .NET runtime gets patched), but you should be able to work as you could with .NET 2.0. So what did we do? First, I implemented a workaround for the "copy local" bug. I don't know why that bug occurs only when targeting AnyCPU, but I understand why this depends on the reference assemblies: MSBuild uses a file called "RedistList\FrameworkList.xml" to decide which references should, by default, be copied into the application directory, and which are part of the .NET framework and thus always present in the GAC. This file is part of the reference assemblies, so MSBuild must be using something else when those aren't installed. The workaround in SharpDevelop adds a custom MSBuild task to the assembly resolution target, which sets CopyLocal=false for all .NET assemblies (for this purpose, SharpDevelop contains a hard-coded list of .NET assemblies).

Second: I found the MSBuild warning really annoying - it appears once per reference, so that's a few hundred warnings in a large solution. SharpDevelop 4.0 now simply ignores MSB3644. Together, these two small changes make builds of .NET 4.0 projects work as expected, even if no Windows SDK is installed. By the way: you can also use our workaround for the "copy local" bug in command line builds: call MSBuild with the parameter /p:CustomAfterMicrosoftCommonTargets=path-to-sharpdevelop\bin\SharpDevelop.TargetingPack.targets

Have you ever have mistake like  "MSB3245: Could not resolve this reference. Could not locate the assembly "RadDock.Net2". Check to make sure the assembly exists on disk. If this reference is required by your code, youmay get compilation errors."?

You can try to fix this problem like:

AdditionalReferencePath can be found in TFSBuild.proj file.

<ItemGroup>
    <!--  ADDITIONAL REFERENCE PATH
     The list of additional reference paths to use while resolving references. For example:
         <AdditionalReferencePath Include="C:\MyFolder\" />
         <AdditionalReferencePath Include="C:\MyFolder2\" />
    -->
    <AdditionalReferencePath Include="Path to the Dependencies folder" />
  </ItemGroup>

For example: <AdditionalReferencePath Include="C:\Program Files\Reference Assemblies\Microsoft\Framework\v4.0\Profile\Client\" />

Or you can just Install Visual studio 2008 SP1 and  It will be ok, but not always.

If you've tried to compile for .NET 4.0 using MSBuild on the command line without having the Windows SDK or Visual Studio 2010 installed, you'll probably have noticed this warning message:

warning MSB3644: The reference assemblies for framework ".NETFramework,Version=v4.0" were not found. To resolve this, install the SDK or Targeting Pack for this framework version or retarget your application to a version of the framework for which you have the SDK or Targeting Pack installed. Note that assemblies will be resolved from the Global Assembly Cache (GAC) and will be used in place of reference assemblies. Therefore your assembly may not be correctly targeted for the framework you intend.

One issue that popped up was that now all builds were targeting MSBuild 4.0. That doesn’t seem to be a big problem until our CruiseControl CI server kicked in, downloaded our updated code and failed building the upgraded projects. Fortunately there is a very quick solution to this little problem.  There are a couple of requirements.

  1. You need to have VS2010 RC installed somewhere
  2. You need to download the .Net Framework 4.0 (I recommend the full version and not just the Client Profile, it ensures you don’t miss anything)

To fix, do the following:

  1. download and install the .Net Framework 4.0 on the CI server (then restart the server)
  2. on the computer where VS2010 RC is installed go to the following path:
    %programfiles%\MSBuild\Microsoft\VisualStudio
  3. copy the v10.0 folder located in that directory into the CI server at the same path (or wherever our MSbuild path is on the CI server)
  4. Once that is done, edit the ccnet.config file at the <msbuild><executable> tag and change it to the new .Net 4.0 Framework installed (you should only need to change the section “\v3.5\” to “\v4.0.xxxxx\”

MSBuild 4.0 and MSBuild 3.5 problems on TFS Continuous Integration server

How to Configure TFS Server to Build Solutions v.2008 and v.2010 Side by Side on the Same Machine

Step by Step Instructions

  1. Go to folder: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Private Assemblies
  2. Find files TFSBuildService.exe and TFSBuildService.exe.config
  3. Create copies of these files in the same folder: TFSBuildService2.exe and TFSBuildService2.exe.config
  4. Open TFSBuildService.exe.config file.

    Change element:

    <add key="MSBuildPath" value="">

    to:

    <add key="MSBuildPath" value="c:\windows\microsoft.net\framework\v4.0.21006\"> 
  5. Open TFSBuildService2.exe.config file.

    Change element:

    <add key="MSBuildPath" value=""> 

    to:

    <add key="MSBuildPath" value="c:\windows\microsoft.net\framework\v3.5\">

    Change element:

    <add key="InteractivePort" value="9192">

    to:

    MSBuild 4.0 and MSBuild 3.5 problems on TFS Continuous Integration server Collapse
    <add key="InteractivePort" value="9194">
  6. Now restart "Visual Studio Team Foundation Build" Windows service on build machine (go to Control Panel/Administration Tools/Services).

MSBuild 4.0 and MSBuild 3.5 problems on TFS Continuous Integration server

  1. Create shortcut for TFSBuildService2.exe. I would recommend to add this shortcut to Startup.
  2. Run TFSBuildService2.exe. You will see a console window opened. Do not close it. While it is open, your build server is being able to build solutions v2008.
  3. Open Visual Studio 2008, Team Explorer, right click on Builds folder in your project, select Manage Builds Agents. "Manage Build Agents" window will be opened. (Note: You should use namely VS 2008 because I did not find corresponding menu item in VS 2010 Beta 2. They will definitely fix it in release.)
  4. Now we have to create two build agents:
    • "Agent 2008" with following parameters:
      Computer name: <name of build machine>
      Communications port: 9194
      Working directory: <path on build machine where sources for 2008 will be located>
    • "Agent 2010" with following parameters:
      Computer name: <name of build machine>
      Communications port: 9191
      Working directory: <path on build machine where sources for 2010 will be located>

      Note: Working directories for 2008 and 2010 must be different!

  5. In Team Explorer, select a build that has a solution of version 2008, right click and select Edit Build Definition and then go to Build Defaults and select Agent 2008. Close the window.

  6. In Team Explorer, select a build that has a solution of version 2010, right click and select Edit Build Definition and then go to Build Defaults and select Agent 2010. Close the window.

Just one line <add key="MSBuildPath" value="c:\windows\microsoft.net\framework\v4.0.30319\" /> that was added to  this file C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\TFSBuildService.exe.config" solved problems for my build system on Visual Studio 2010 .NET 4.0 project with TFS + MSBuild.

References

TFS Server to Build Solutions v.2008 and v.2010 on the Same Machine

Compiling for .NET 4.0 without installing the Windows SDK

MSDN MSBuild

Summary

Although you could build the .net 4.0 project with MSBuild 3.5 successfully, but there may be some hidden problems. Because MSBuild 4.0 has some changes in its targets.

If you have done some investigation, you will find the Copy to output directory is actually in done in _CopyFilesMarkedCopyLocal targetwhich locate in Microsoft.common.Targets, but this target was never called when you build 4.0 project using MSBuild3.5, that’s why the dll or exe doesn’t copy to the output directory. Actually , as I invested, even the AfterBuild Target was not called in your condition. I assume that this article will save 1 or 3 days for your build engineering team, Integration lead or Continous Integrator. Good luck and have fun with Continuous Integration integration.

MSBuild 4.0 and MSBuild 3.5 problems on TFS Continuous Integration server

Add comment

Loading

Copyright © 2018 - Design by FS