October 2004 - Posts

Creating GUIDs in VS 2005 B1

In VS.NET 2003 there is an external tool called 'GuidGen' to generate GUIDs. I can't seem to find this in VS 2005 so I made my own:

class Program
{
    public const string ARG_BYTES = "/b";
    public const string ARG_CSHARP = "/cs";
    public const string ARG_HELP = "/?";

    static void Main(string[] args)
    {
        StringBuilder builder = new StringBuilder();

        if (args.Length > 0)
        {
            switch (args[0])
            {
                case ARG_BYTES:
                    foreach (byte b in Guid.NewGuid().ToByteArray())
                    {
                        builder.Append(b.ToString("X2"));
                        builder.Append(" ");
                    }
                    break;
                case ARG_CSHARP:
                    builder.Append("new byte [] { ");
                    foreach (byte b in Guid.NewGuid().ToByteArray())
                    {
                        builder.Append("0x");
                        builder.Append(b.ToString("X2"));
                        builder.Append(", ");
                    }
                    builder.Remove(builder.Length - 2, 2);
                    builder.Append(" }");
                    break;
                case ARG_HELP:
                default:
                    builder.Append(string.Format("Usage: no arguments for a hexString representation, {0} for a byteArray representation, {1} for a C# byte array, {2} for this help message", ARG_BYTES, ARG_CSHARP, ARG_HELP));
                    break;
            }
           
        }
        else
        {
            builder.Append(Guid.NewGuid().ToString());
        }

        Console.Write(builder.ToString());
    }
}

 

At the command line type:

"GuidGen" for output like "ab04c0a1-ebb7-4996-914f-2a16ca9212f4"

"GuidGen /b" for output like: "31 34 37 18 5F 5B 2A 45 BC 8C 32 06 37 BF E9 B6"

"GuidGen /cs" for output like "new byte [] { 0x38, 0x39, 0xC0, 0xBD, 0xCE, 0xD4, 0xEC, 0x41, 0x8C, 0x90, 0x7C, 0x96, 0x37, 0x35, 0x83, 0x1C }"

Using the Microsoft SDC MSbuild tasks

Microsoft Research UK has released a number of 'extra' tasks for MSBuild on gotdotnet. You can find the workspace here. These tasks include a number of common things, like file management, source control etc... You can find a complete list of tasks at Jamie Cansdale's NunitAddin weblog here.

The mechanism for using custom tasks in MSBuild is with an <Import/> statement in your build file.

<Import Project="C:\WINDOWS\Microsoft.NET\Framework\v2.0.40607\Microsoft.Sdc.Tasks"/>

After that, you can use the tasks in your build file and msbuild will recognize them.

Of course, you still need to create the '.tasks' file that points the msbuild framework to the assembly that contains the task. This mechanism is widely used by the msbuild framework and in itself, its just a build file that uses the <UsingTask> task :-). It looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="
http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask AssemblyName="Microsoft.Sdc.Tasks, Version=2.0.5000.0, Culture=neutral, PublicKeyToken=e24a7ed7109b7e39" TaskName="Microsoft.Sdc.Tasks.ActiveDirectory.Group.AddUser" />
  <UsingTask AssemblyName="Microsoft.Sdc.Tasks, Version=2.0.5000.0, Culture=neutral, PublicKeyToken=e24a7ed7109b7e39" TaskName="Microsoft.Sdc.Tasks.ActiveDirectory.Group.Create" />
  <UsingTask AssemblyName="Microsoft.Sdc.Tasks, Version=2.0.5000.0, Culture=neutral, PublicKeyToken=e24a7ed7109b7e39" TaskName="Microsoft.Sdc.Tasks.ActiveDirectory.User.Create" />
...
</Project>

Next, you put this file and the assembly in the .NET framework folder (c:\windows\microsoft.net\framework\v2.0.40607).

I was getting errors running the SDC tasks because they seemed to overlap tasks already present in the basic MSBuild framework (I don't know if this was related to my desktop install or something else). Just renaming the '.tasks' file that came with the SDC tasks to '.tasks2' and updating my import statement above made the errors go away. (spooky :))

By doing these three simple things, you can start using custom tasks in your build files:
1. create a '.tasks' file that lists the custom tasks in an assembly
2. copy the '.tasks' file and the assembly somewhere msbuild will find them (the framework dir is the easiest)
3. use an <import> statement to reference the tasks in your build file

How to use the SDC tasks:
When you extract the zipfile from the gotdotnet workspace, you should look in the following folder:
<zipfile>\Microsoft.Sdc.Tasks\MainTempGDN\Framework2.0

In this folder, you will find another zipfile, called 'GDN2.0.041008.124.zip'. Extract this zipfile and look in the following folder:
<new zipfile>\Microsoft.Sdc.Tasks\MainTempGDN\Install

This folder contains everything you need to get started (apart from the docs :-)). Copy everything in this folder to your .NET framework folder (the v2.0.40607 one). You might experience the same 'overlap' problem I explained above, but that can be solved easy :-).

You can find a sample build file that uses some of the SDC tasks (mostly file & folder mgmt) here.

Next time, I'll talk about how to create a custom task yourself, and how to port a Nant or NantContrib task to MSBuild. I needed it because I couldn't get the source control tasks in the SDC build to work, so I ported the Nant VSS tasks.

CruiseControl.NET and MSBuild

Hi all,

This is my first post to this blog, and I wanted to make it a more memorable one than 'this is a test' ;-)

This blog is (among other more worldly things I hope) going to be about automated builds. I'm currently working on a project that is in a proof-of-concept stage and is using Visual Studio 2005 Beta 1 and, by extension, the version of MSBuild that comes with it (v2.0.40607.16). In itself, that's not that unusual, but we also started out with the idea of automating builds and incorporating a number of good software practices or concepts in the build process (unit testing, static analysis, outputting reports to developers etc...).

If you start looking around the web for an automated build solution for .NET that can also function apart from Visual Studio, you'll probably end up with a combination of NAnt on the one side and CruiseControl.NET, Hippo.NET or Draco.NET on the other side. NAnt is the answer to scripting the real work behind your build process, and the other tools provide you with (a.o.) a way to schedule those builds (or execute on-demand builds) and a nice overview of past and current build results and reports.

What you don't get is a way to combine one of these tools with MSBuild. Of course, you can do this with NAnt by using the <exec> task to start msbuild.exe, but I wanted to cut out the middle man. Note: I do NOT want to start a religious war here and i don't consider MSBuild to be better than NAnt (or vice versa). Let's just say I wanted to make it more challenging by veering away from the path most travelled :-).

So here's a short overview and a sample of my experiences with running CruiseControl.NET (ccnet for short) with MSBuild instead of NAnt.

First of all, ccnet uses an xml configuration file to drive the build process: ccnet.config. This file is included in every 'server' folder in your ccnet setup. Next, it has a mechanism called 'builders' that delegate the actual build process to a more specialized tool. The <build> node in the ccnet.config xml file will be used to drive the builder.

Out of the box, a builder for NAnt (if you download the source, look for a file called NAntBuilder.cs) is included. When you look at the code, you'll see it's fairly easy to replace the arguments needed to run nant.exe with those needed to run msbuild.exe and hey-presto! - MSBuilder.cs is born.

The first thing you'll notice in the bowels of ccnet is that it uses a component called Exortech.Reflector to map builder properties onto xml. This means that you can decorate .NET properties with attributes that declare which xml nodes are going to be used to fill the properties with data.

This code:
[ReflectorProperty("buildArgs", Required = false)]
  public string BuildArgs;

Will be filled in by the <buildargs> node in the following xml:
    <build type="msbuild">
      <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.40607\MSBuild.exe</executable>
      <baseDirectory>d:\temp\</baseDirectory>
      <buildArgs>@mybuild.response</buildArgs>
      <buildFile>mybuild.proj</buildFile>
      <targetList>
        <target>Build</target>
      </targetList>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
    </build>

What you basically have to do is figure out what information you need to pass onto the msbuild executable, translate this into appropriate xml, and provide properties in the 'builder' that read the xml.

Download the MSBuilder.cs file here.

The way you get ccnet to use your custom builder is either by adding it to the ccnet source code and rebuilding it, or by building it into a plugin. You can create a plugin as follows:
- create a VS.NET 2003(!) library project
- add your custom builder to the project
- add the appropriate references (exortech reflector and a number of 'core' ccnet dlls)
- name the output of the project 'ccnet.<insert name here>.plugin.dll
- place the plugin dll in the 'server' folder of your ccnet project

Next, you can replace the standard <build> node in the ccnet.config file with the above 'msbuild' <build> node, write a small msbuild script ('.proj' file) and you're off.

In short:
1. build the custom 'builder' into a plugin dll
2. put the plugin dll in the ccnet server folder
3. put the custom xml in ccnet.config
4. point the custom xml to an appropriate msbuild script
5. force the ccnet project to build through its website (or schedule it) and watch the magic happen :-)

Coming up next on this blog:
- using the Microsoft SDC MSBuild tasks to do lots of stuff (source control, file management, nunit, fxcop, ...)
- creating custom MSBuild tasks yourself (or stealing them from NAnt) (it's not really stealing as long as you re-release them under the (L)GPL, is it ?)
- Whatever you want to hear, as long as its about MSBuild and/or CCNET