Tuesday, May 4, 2010

Upgrading your build server to use .Net 4 + Nant

At work we use CruiseControl.net + Nant for our continuous integration. Recently we have upgrades to VS2010 and .Net 4.0 (awesome so far). Alas, as soon as we converted our solution to .Net 4.0, our build server broke! After googling and wrestling for 2 days with build errors, I finally got the build server running again. I found most of my questions on Stack overflow, however I had this "AL exited with code 128" build error that I could not get past and it was driving me crazy! So, below are the steps to upgrade to .Net 4.0 and to solve the "AL" error message (that hopefully you won't get):

First thing. You DO NOT need to intall VS2010 in the build server like many people think. You do have to install the latest Windows SDK. (I believe 7.0)

1) Install .Net 4.0 Framework.

2) Install latest Windows SDK.

Install the latest Windows SDK, then go to the registry and copy the key "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0" and rename all instances of 7.0 to 7.0A. The Build server is going to look at that path in order to get the "Installation Folder key". Alternatively, You can copy the text below into a notepad and save it as "whatever.reg", then run it and it should import the key and subfolders into the registry.

*~~~~~~~~~~~~~~~~~~~~ Copy everything below this line ~~~~~~~~~~~~~~~~~~~~~~

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\"
"ProductVersion"="7.0.30319"
"ProductName"="Microsoft Windows SDK for Visual Studio 2010"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx35Tools]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK .NET Framework 3.5 Multi-targeting Utilities"
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Bin\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools]
"ProductVersion"="7.0.30319"
"ComponentName"="Windows SDK Tools for .NET Framework 4.0"
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Bin\\NETFX 4.0 Tools\\"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-SDKTools]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Bin\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Common Utilities"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-Win32Tools]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Bin\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Utilities for Win32 Development"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-WindowsHeadersLibs]
"InstallationFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Headers and Libraries"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-WinSDKIntellisenseRefAssys]
"InstallationFolder"="C:\\Program Files\\Reference Assemblies\\"
"ProductVersion"="7.0.30319"
"ComponentName"="Windows Intellisense and Reference Assemblies"

*~~~~~~~~~~~~~~~~~Do not include this line~~~~~~~~~~~~~~~~~~~~~

3) Modify your Nant.exe.config file.

Towards the end of your Nant.exe.config file, modify the <startup> section to add .Net 4.0 as a supported Runtime:

<supportedRuntime version="v4.0.30319" />.

Also, under the <properties> section, add a property:

<property name="nant.settings.currentframework" value="net-4.0" />

This will make your builds default to that framework. You can also put this property in your projects Nant file, so you can tell each project what version to target. Finally, you need to add the .net4.0 framework node. Here is a link to that configuration section: http://pastebin.com/3ghS0gyA

4) Review the Build section of your Nant file

I was using the msbuild task for NantContrib. That still works, but if it doesn't, you can always use the <exec> task and call msbuild.exe like so:

<property name="msbuild.exe" value="C:\WINDOWS\Microsoft.NET\Framework\v4.0\MSBuild.exe" />    

<exec program="${msbuild.exe}">        
        <arg line="/property:Configuration=${YourSolutionConfigurationHere}" />         
        <arg line='"${YourSolutionFileFullPathHere}"' />         
        <arg value="/target:Rebuild" />         
        <arg value="/verbosity:normal" />         
        <arg value="/nologo" />         
</exec>

5) Random Errors

I ran into some weird build errors: "error MSB6006: "AL.exe" exited with code 128" That's it, not helpful at all. I did some googling and came up with few answers. Here are the links: msdn help and asp.net forums.  I wrestled with that error for a full day, studying the "detailed" and "diagnostic" logs, but all it did is pointing me to the assembly that failed building. No specific error. I could not even duplicate it on my local box.

Finally, I decided to try the suggestion about the "resource" files naming convention in the asp.net forum link, and... alleluia! my build started working. I don't know what's up with the build failing because of the resource name, still working on that, but my immediate goal was to get the build working.

StackOverflow related posts:

http://stackoverflow.com/questions/1215731/building-net-4-projects-with-nant
http://stackoverflow.com/questions/2353404/nant-msbuild-task-with-net-4-0-rc
http://stackoverflow.com/questions/1291221/going-from-solution-to-exec-programmsbuild-in-nant

Hope this helps someone else out there.

-D

13 comments:

Andriy said...

hello Diego, thanks for this great tutorial. Where do I get the Windows SDK 7.0A. No way to find it on the msdn even in subscriber's downloads.

Is it the "Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO)" that one needs to run the builds w/o VS2010 on the server?

In the registry on a PC, where I have VS2010 installed I see ProductName=Microsoft Windows SDK for Visual Studio 2010. I can find it nowhere though.

Thank you for your assistance.

Kind regards, Andriy

Diego Cadenas said...

Hey Andriy, I'm glad you found the post useful.

Yes, you have to download the "Microsoft SDK for Windows 7 and .Net Framework 3.5 SP1". Download it here

I couldn't find the SDK 7.0A either, and for some reason msbuild.exe always looks at that location. What I did was copy the 7.0 registry key that gets installed with the download above and create a new registry key renaming every 7.0 to 7.0A. You can always just copy the text I posted on the post and create the registry key using that.

The registry key should be under "HKEY_LOCAL_MACHINE"/Software/Microsoft/Microsoft SKDs/Windows

Hope this helps

Andriy said...

Hi Diego, I got it. I can now build my project on the FinalBuilder Server without having to install the Visual Studio 2010.
The Microsoft Windows SDK for Windows 7 was required, but not sufficient in my case. As I also had a project with unit tests, there was one assembly reference missing, that comes with the VS 2010. That is Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll residing in C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies. It has to be included in the project and referenced from there.
Thanks again for your help!

Diego Cadenas said...

Great! Glad it worked out for you and good to know about that Unit test assembly

Max said...
This comment has been removed by the author.
Max said...

Hey Diego

Thanks for this guide. I have followed your instructions but when I include the framework section in the config file nant complains:

[loadtasks] Failure scanning "C:\Nant\bin\NAnt.CompressionTasks.dll" for extensi
ons. Could not load file or assembly 'file:///C:\Nant\bin\NAnt.CompressionTasks.
dll' or one of its dependencies. Operation is not supported. (Exception from HRE
SULT: 0x80131515)

along with a lot of other loadtask failures and then finally says:

Failed to initialize the 'Microsoft .NET Framework 4.0' (net-4.0) target framewo
rk.

Invalid element [readregistry] . Unknown task or datatype.

Do you have any idea what that is? I have installed the SDK on windows server 2008 R2, added the registry keys and I'm using nant 0.90

Thanks!

Diego Cadenas said...

Hey Max,

I am not sure why you are getting that error. Here is what I would do:

1) get the latest version of Nant (nightly build) and modify the Configuration file to add .net40

2) Get the NAnt 0.91 Alpha 1 Release that includes the .net40 already configured

Let me know if that fixes the issue

Diego

Camilo said...
This comment has been removed by the author.
Camilo said...

Diego, I was having this issue and it took me a while to fix:

Unhandled Exception: System.TypeInitializationException: The type initializer fo
r 'NAnt.Console.ConsoleStub' threw an exception. ---> System.Security.SecurityEx
ception: Request for the permission of type 'System.Security.Permissions.FileIOP
ermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5619
34e089' failed.

No information on the internet about that can be found, but I saw this tag in the nant.exe.config:

NetFx40_LegacySecurityPolicy enabled="true"

I remarked the tag and things started to roll better.

Keep up the good work, your guide is really helpful although I didn't need the registry keys, the other stuff is really useful.

Thanks a lot

Camilo

Diego Cadenas said...

Hi Camilo,

Thank for posting that info. I think it will be helpful for others to see how you solved that issue.

Thanks for visiting!

Camilo said...

For Max:

Check that the dlls in the nant directory are not blocked:

http://www.windows-stupidities.com/This_file_came_from_another_computer_and_might_be_blocked_to_help_protect_this_computer.php

Camilo

brahimster said...

Thank you very much ! :)You saved my life

Anonymous said...

Hello Diego,

I aslo have failure scanning NAnt.Contrib.Tasks.dll message:

http://stackoverflow.com/questions/17472717/failure-scanning-nant-contrib-tasks-dll

I have other project - ant its work good there but in my new project - where I have copy of NAnt.Contrib.Tasks.dll it doesnt..

Can you help me please?

MikroDel