Fake binary trees
... rants, ramblings and occasional good idea ...

Build automation issues wit NAnt and .NET 3.5

On our project, we are experimenting with continuous integration, and so we set up a build server based on CruiseControl.NET. The server is running on Windows Server 2008, and we try to keep it as clean as possible. Development machines typically run on Win XP.

The project tree contains tools folder which contains copy of NAnt and other tools which are used to run the build (NUnit, NCover, Simian, etc). This way, when a developer downloads project files to development machine, he just runs the build script and same version of tools is used to perform a local build, thus avoiding the risk of using mismatching version of tools. NAnt build script internally uses <msbuild> task to compile the msbuild solutions.

This has all worked great until we recently switched from .NET 2.0 to .NET 3.5. During this, our development machines were updated to Visual Studio 2008, and our build server was updated to 3.5 framework and SDK (we don't install Visual Studio on build server,so we have to install SDK separately after the .NET framework is installed).

This initially created issues with some of our build scripts: builds started failing with error messages pointing to the fact that <msbuild> task doesn't understand format of the solution file (new version is 10 and build complained about understanding only 7 and 9). After updating NAnt to latest version and testing on a dev machine, problem seemed to went away.

However, builds on our CI build server started failing with same error.

After some investigation, it turned out that Visual Studio 2008 installs version 6.0A of Windows SDK. However, standalone Windows SDK installs version 6.1, thus resulting in mismatch between build server and dev machines.

The heart of the problem is that nant.exe.config internally uses ${sdkInstallRoot} variable which is initialized to the value read from the registry key SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A\WinSDKNetFxTools\InstallationFolder. Now, we couldn't just change the entry in nant.exe.config because the same file is used both on server and dev machines, and if we fix it for one it won't work for the other.

We also didn't want to install Visual Studio 2008 on build server.

The solution (or more precisely, the hack) was simple:

  • Open regedit
  • Go to 'SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.1\WinSDKNetFxTools\InstallationFolder' key
  • Export it into a file
  • Open the file and replace all references in key names from "v6.1" into "v6.0A". Leave the file paths with 'v6.1' unchanged.
  • Save the file and import it into regedit

Now you have the exact copy of the SDK 6.1 keys, saved under 6.0A key. This way, build server can use the same nant.exe.config file as dev machines.

If there is a cleaner way, I would be glad to hear it, but this is working for us without any problems.

Posted at 14:03 on September 24, 2008
Categories: .NET | Continuous Integration | NAnt   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed

Using timestamps in batch files

After failing many times before, I have finally found out how to create user-friendly timestamps in batch scripts. For many people this may be yesterday's news, but I am posting it here as a reminder to myself and in hope that it might help someone else.

Windows command shell (sometimes erroneously called DOS prompt) provides %DATE% and %TIME% environment variables which, unsurprisingly, return current date and time. On the other hand, it is possible to extract a group of characters from any environment variable using following syntax:

%VARIABLE:~START,LENGTH%

where VARIABLE is the name of the environment variable, START is the zero-based index of the first character to be retrieved and LENGTH is the length of the string to be retrieved. E.g. %USERNAME:~1,3% would return second, third and fourth letter of the current user's name.

So in order to create a time stamp, we define a temporary environment variable with value defined by parts of %DATE%  and %TIME%. Then we use this variable to create file names. Please note that the exact indices will depend on your time format settings. In a batch file or a script it would look like this:

set backup_time=%date:~10,4%_%date:~7,2%_%date:~4,2%
set backup_detailed=%date:~10,4%_%date:~7,2%_%date:~4,2%__%time:~0,2%_%time:~3,2%_%time:~6,2%
md d:\zzz_%backup_time%
md d:\zzz_%backup_detailed%

Output of the batch file is:

D:\tmp>set backup_time=2008_09_23
D:\tmp>set backup_detailed=2008_09_23__15_50_31
D:\tmp>md d:\zzz_2008_09_23
D:\tmp>md d:\zzz_2008_09_23__15_50_31
Posted at 15:46 on September 23, 2008
Categories: General   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed

Using assembly resources as NVelocity templates

For those who don't already know, NVelocity is a .NET port of Jakarta Velocity template engine. Castle team took it over, due to the lack of releases, support and bug fixes on the original port, and I strongly suggest to use this improved version.

NVelocity is a fine tool, but it is not quite obvious how to set it up so that embedded assembly resources can be used as templates. This is done by setting a group of properties which control what implementation of ResourceLoader abstract class is used to load the templates. To use embedded resources, you need to register the NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader class as ResourceLoader, and specify the assembly which contains the templates as parameter "assembly.resource.loader.assembly". Here's how: 

private static void InitializeVelocity()
{
  ExtendedProperties properties = new ExtendedProperties();

  properties.AddProperty("resource.loader", "assembly");
  properties.AddProperty("assembly.resource.loader.class",
          "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader, NVelocity");
  properties.AddProperty("assembly.resource.loader.assembly",
          Assembly.GetExecutingAssembly().GetName().Name);
     
  m_velocity = new VelocityEngine(properties);
}

You can find the full sample here: NVelocitySample.zip (87.13 kb)

Posted at 18:34 on September 19, 2008
Categories: .NET | NVelocity   E-mail | del.icio.us | Permalink | Comments (0) | Post RSSRSS comment feed