Bart's Blog

Just another WordPress.com weblog

  • Categories

  • Archives

CruiseControl integration problems when upgrading to Visual Studio 2010, .NET 4.0 and MVC 2.0

Posted by bartmaes on April 23, 2010

Yesterday, I upgraded a website solution from Visual Studio 2008 to Visual Studio 2010. I also upgrade all projects to target the .NET 4.0 framework and MVC 2.0. (Some small changes needed to be applied in the code to be compatible with the new IValueProvider.) When I committed the code in our source control system, there were a few things to be solved on our CruiseControl integration server:

  • I already installed the .NET 4.0 framework on the CruiseControl server using the Microsoft .NET Framework 4 standalone installer (which doesn’t require an internet connection during installation).
  • The build on the build server fails with the error message: “The type or namespace name ‘Mvc’ does not exist in the namespace ‘System.Web’ (are you missing an assembly reference?)”. Apparantely the MVC 2.0 libraries are not part of the .NET framework 4.0 installation, so I installed these seperately. Since I have no internet connection on the build server, I couldn’t use the Web Platform Installer 2.0, so I installed the ASP.NET MVC 2 RTM seperately.
  • I force a new build and this one fails again with 2 new error messages: “The type or namespace name ‘Routing’ does not exist in the namespace ‘System.Web’ (are you missing an assembly reference?)” and “The type or namespace name ‘RouteValueDictionary’ could not be found (are you missing a using directive or an assembly reference?)”. After a little bit of thought and opening the System.Web assembly in reflector, I found out that RouteValueDictionary is defined in the System.Web assembly in the .NET 4.0 framework. The problem was that I was still using the old version of MsBuild for building the solution. Our CruiseControl uses a configuration file located at “C:\Program Files\CruiseControl.NET\server\CruiseControlConfig” and was indeed configured to use MsBuild.exe from the .NET 3.5 framework. So I changed the setting:

    <msbuild>
            <executable>C:\windows\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>

    to

    <msbuild>
            <executable>C:\windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
  • My next build still fails, this time with the error message: “The type or namespace name ‘VisualStudio’ does not exist in the namespace ‘Microsoft’ (are you missing an assembly reference?)”. When searching in the solution, I see that the test projects (containing unit tests written using NUnit) in the solution reference “Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll”. This dll is installed together with Visual Studio 2010, but is not part of the standalone installer. I did not find an installer on the internet to install the quality tools seperately. From this moment on, I asked a colleague, who had already done some upgrades to the release candidates of Visual Studio 2010, for help. According to him, Microsoft advices to install Visual Studio 2010 on your build server, but does this mean that you have to install any component from any vendor on your build server just because one or another product makes use of it. And what happens if those vendors release updates of those products. So we copied the “Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll” into the references folder of our project and added it in our source control system. Now we just had to make sure that the dll was found on our build server. Since the dll is added as a .NET reference, the <HintPath> is not automatically set. So we changed the .csproj files of our test projects manually (by first unloading the projects in Visual Studio and then right-clicking them to edit the xml). We changed
    <Reference Include=Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL />
    into
    <Reference Include=Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL“>
     
    <
    HintPath>..\..\references\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll</HintPath>
    </
    Reference>
    Notice that the HintPath is relative to the .csproj file. This makes sure that the dll can be found on the build server where the absolute path is different.
    In fact since the test projects were using NUnit and not MsTest, we also could have replaced the Test projects with regular class library projects and get rid of the reference to the dll…
  • My next build on the build server still fails, but the “MsBuilding” of the project already works. When I look at the end of the Build Log, I get a clue of what’s wrong:

    <![CDATA[ProcessModel: Default    DomainUsage: Single
    Execution Runtime: net-2.0.50727.3603
    Unhandled Exception:
    System.BadImageFormatException: Could not load file or assembly ‘C:\src\MyProject.UnitTest\bin\release\MyProject.UnitTest.dll’ or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
    File name: ”C:\src\MyProject.UnitTest\bin\release\MyProject.UnitTest.dll’Server stack trace:
       at System.Reflection.AssemblyName.nGetFileInformation(String s)
       at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile)
       at NUnit.Core.Builders.TestAssemblyBuilder.Load(String path)
       at NUnit.Core.Builders.TestAssemblyBuilder.Build(String assemblyName, Boolean autoSuites)
       at NUnit.Core.Builders.TestAssemblyBuilder.Build(String assemblyName, String testName, Boolean autoSuites)
       at NUnit.Core.TestSuiteBuilder.BuildSingleAssembly(TestPackage package)
       at NUnit.Core.TestSuiteBuilder.Build(TestPackage package)
       at NUnit.Core.SimpleTestRunner.Load(TestPackage package)
       at NUnit.Core.ProxyTestRunner.Load(TestPackage package)
       at NUnit.Core.ProxyTestRunner.Load(TestPackage package)
       at NUnit.Core.RemoteTestRunner.Load(TestPackage package)
       at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
       at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
       at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at NUnit.Core.TestRunner.Load(TestPackage package)
       at NUnit.Util.TestDomain.Load(TestPackage package)
       at NUnit.ConsoleRunner.ConsoleUi.Execute(ConsoleOptions options)
       at NUnit.ConsoleRunner.Runner.Main(String[] args)Assembly manager loaded from:  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
    Running under executable  C:\Program Files\NUnit 2.5\bin\net-2.0\nunit-console.exe

    I also have a lot of warnings, but I’ll get back to that in the next paragraph… The problem is that NUnit uses the wrong version of the .NET framework for loading the UnitTest dll. Since our build server is using nunit-console.exe, we open the “C:\Program Files\NUnit 2.5\bin\net-2.0\nunit-console.exe.config” file in a text editor and we add:
       <startup>
          <supportedRuntime version=”v4.0″/>
       </startup>
    under <configuration>. (We might have added extra supported runtimes, but apparently this was not necessary on our build server…). After reforcing a new build, the build succeeds!

  • However there a still a lot of warnings with the message:
    C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (847,9): 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.

    We search in our project where these error messages come from. In every .csproj file, we find the same string “.NETFramework,Version=v4.0”:
    <ItemGroup>
      <BootstrapperPackage Include=.NETFramework,Version=v4.0>
        <
    Visible>False</Visible>
        <
    ProductName>Microsoft .NET Framework 4 %28×86 and x64%29</ProductName>
        <
    Install>true</Install>
      </
    BootstrapperPackage>
      <BootstrapperPackage Include=
    Microsoft.Net.Client.3.5>
        <
    Visible>False</Visible>
        <
    ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
        <
    Install>false</Install>
      </
    BootstrapperPackage>
      <BootstrapperPackage Include=Microsoft.Net.Framework.3.5.SP1>
        <
    Visible>False</Visible>
        <
    ProductName>.NET Framework 3.5 SP1</ProductName>
        <
    Install>false</Install>
      </
    BootstrapperPackage>
      <BootstrapperPackage Include=Microsoft.Windows.Installer.3.1>
        <
    Visible>False</Visible>
        <
    ProductName>Windows Installer 3.1</ProductName>
        <
    Install>false</Install>
      </
    BootstrapperPackage>

    </ItemGroup>

    This section was added when upgrading the solution to Visual Studio 2010 and the BootstrapperPackage for .NET 4.0 must have been added when upgrading the project to target .NET 4.0. When adding new projects to the solution, the the BootstrapperPackages are not added to the .csproj files. The only reason we can come up with why the BootstrapperPackages are needed in the .csproj files is if you would want to be able to deploy the project with ClickOnce.
    Because we want to avoid having to change the .csproj files for every project that we upgrade to .NET 4.0 in the future, we start searching for a solution. This morning, I receive a mail from my colleague who solved this final issue. According to him, the reference assemblies are installed together with the .NET 4.0 framework standalone installer, but they are installed in the GAC and not found in the directories where the build server is looking. One way to get rid of the errors is to install the .NET Framework 4.0 SDK or any other application that installs the .NET 4.0 Multi-Targetting Pack (which cannot be installed alone). The solution we choose was to manually copy the reference assemblies from our development server to our build server (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\).

It has taken us a while, but finally everything seems to work propertly…

One Response to “CruiseControl integration problems when upgrading to Visual Studio 2010, .NET 4.0 and MVC 2.0”

  1. Paige Cook said

    Thanks for this posting. We were having the some of the same issues and your solutions saved us a lot of time. Appreciate you posting this information.

Leave a comment