Its quite common to use pre and post build events in your c# projects. You enter the command you want to run in the project properties, like below.

Prebuild event

But this isn’t the only way to achieve this. There is another way by editing your .csproj file and using the BeforeBuild target. 

First lets look how the PreBuildEvent from the project properties is actually handled. At the bottom of your project file you’ll find a property that lists your command. 

<PropertyGroup>
  <PreBuildEvent>copy $(OutDir)\test.blah c:\test</PreBuildEvent>
</PropertyGroup>

If you follow your imports in your project file you’ll find that your PreBuildEvent is handled by the PreBuildEvent target in Microsoft.Common.Targets. What does this do? It calls the Exec task on your command, which runs in as any other command prompt command.

<Target
    Name="PreBuildEvent"
    Condition="'$(PreBuildEvent)'!=''"
    DependsOnTargets="$(PreBuildEventDependsOn)">
    <Exec WorkingDirectory="$(OutDir)" Command="$(PreBuildEvent)" />
</Target>

In your .csproj file you will find out two targets (BeforeBuild and AfterBuild) that have been commented out. The other way is to uncomment these and add msbuild tasks. These targets are called exactly when their name suggests.

<Target Name="BeforeBuild">
</Target>

If we want to copy a file then we can use the Copy task

<Target Name="BeforeBuild">
       <Copy SourceFiles="c:\test.txt" DestinationFolder="d:\dest\"/>
</Target>

No command line, no batch files. Just pure msbuild

Powershell as a Calculator

September 25, 2007

I loose count of the number of times I fire up calc.exe everyday to do a quick calculation. I was about to do it earlier today while working in Powershell until I thought, hold on Powershell is .net based, if I type in a number it should treat it as an int or double, and of course it does. So there is no need to start calc.exe just type the calculation straight in:

Powershell Calculator

You couldn’t do that in cmd.exe

In a previous post I mentioned about creating your final output media as part of the build process. This can often include CD or DVDs. A great format to have these in is a .iso file. This is a close to having an actual disk as you can get.

There is nothing in MSBuild to do this for you so i’ve rolled a custom task to do it. Creating an iso file is normally non-trivial but luckily for us Microsoft have added this functionality into the OS with IMAPIv2.

If your running Vista everything you need is installed. For XP Sp2 and Server 2003 you’ll need the following updates.

IMAPIv2 for Server 2003
IMAPIv2 for XP Sp2

IMAPIv2 is COM API which is easy to use in C#. The main implementation in the Execute method is quite simple. Setup the file system, get the root directory, add a tree of files, Create the image and finally copy the image stream to disk.

ifs.MsftFileSystemImage fs = new IMAPI2FS.MsftFileSystemImage();
ifs.FsiDirectoryItem dir = fs.Root;
fs.FileSystemsToCreate = IMAPI2FS.FsiFileSystems.FsiFileSystemISO9660 |
                          IMAPI2FS.FsiFileSystems.FsiFileSystemJoliet;fs.VolumeName = _volumeName;
dir.AddTree(_treeRoot, false);
ifs.FileSystemImageResult res = fs.CreateResultImage();
ifs.FsiStream stream = res.ImageStream;
return CreateISOFile(_outputFileName, (System.Runtime.InteropServices.ComTypes.IStream)stream);

In your msbuild file, add a reference to the target:

<UsingTask TaskName="Belfield.Build.Tasks.CreateOpticalDiskImageTask" AssemblyFile="buildtasks.dll"/>

To create the image call the task in one of your targets

<CreateOpticalDiskImageTask OutputFileName="c:\build\cd.iso"
            TreeRoot="c:\build\output\" VolumeName="My Product" />

Download Source.

(Note: The source project is set to generate CD-ROM images at the moment, for DVDs you need to change the filesystem)

Your build is your friend

September 24, 2007

The build is at the heart of every software project and when starting a project it is always worth spending the time at the start to get it right. Gone are the days when the build was just hitting F5, it is an essential part of the project setup and infrastructure and its worth getting it right.

Continuous Integration is a must, every project should install Cruise Control.Net or similar. Your build process shouldn’t just stop at building the your C# projects. You should be able to produce a full end to end production build in a single go. This is so much more than just compiling code, it should be along the lines of:

  • Labeling and getting latest code from source control
  • Update version and build numbers (make sure those assembly info files are up to date)
  • Generating any data files your app needs
  • Generate release notes, if you’ve got a bug tracker (which you should) then use it to get a list of issues fixed in this build
  • Compiling help files
  • Compiling the Code
  • Pass a full suite of tests (Unit, Regression, Performance)
  • FXCop, if your using it then make sure you can meet your required code quality
  • Obfuscate your code (not really an issue for LOB applications)
  • Signing code (all code should be authenticode signed, its worth doing even for LOB applications)
  • Creating Setup and Deployment packages (these should be integrated in to the build, reject any setup authoring system that requires you to fire up an IDE)
  • Sign msi files (if you have any)
  • Create distribution images (if your distributing on CD or DVD its nice to have a .iso file pop out the end of the build process)
  • For web apps upload them to a staging server (don’t build straight to production, have a staging server you can verify the build on and the a process to promote to production if your happy with it)

Not every project needs all of these steps, but they should form the basis of a successful build. Most of the above can be done inside Msbuild, and the bits that can’t be done out of the box aren’t that difficult to achieve with a few custom actions here and there.

Welcome

September 24, 2007

I thought I should finally get round to creating a blog, and here it finally is.

I’m going to be rambling about c#, .net, wpf, msbuild, powershell and what ever other technologies take my fancy.