10
votes

I have setup CruiseControl.net for a bunch of my projects which are related. As a result a single project tag in CruiseControl has multiple SVN checkouts and then a bunch of msbuild tasks compile all the individual sln files.

I need to update the assembly version of all the solutions when this build is being done. However, since i'm not using nant and not using MSBuild proj files, I am unsure on how to get this.

I wonder if I'm missing something obvious. I just need a solution which can be implemented by making appropriate changes in the ccnet.config file without requiring me to make changes to csproj files.

Thanks, Anj

3
I'm confused. What do you mean when you say "not using MSBuild proj files"? What is referenced by your *.sln files? (Project files created by the IDE, such as *.csproj files, are are just regular msbuild project files, which you can open up and enhance with custom build tasks and targets.)Daniel Fortunov

3 Answers

11
votes

What about using a shared AssemblyInfo across your projects?

This is what we do for our products:

  • Each project has it's own AssemblyInfo.cs - this contains AssemblyTitle, AssemblyDescription, Guid, and other attributes that are unique to that assembly.

  • Each project also has two other Assembly Info files, note that these are added as a link rather than a direct file (VS -> Add -> Existing File -> Add as link (little down arrow next to add))

The two link files:

  1. CompanyAssemblyInfo.cs - AssemblyCompany, AssemblyCopyright, AssemblyConfiguration, CLSCompliant, SecurityPermission, etc. Basically everything we want standard on all our assemblies.

  2. ProductAssemblyInfo.cs - AssemblyProduct, AssemblyVersion, AssemblyFileVersion. This allows us to push the same version across to all assemblies from the one file.

Our CI and release process is more complicated, but that's at the heart of it - a single point (file) which controls the product version (assemblies, installers, everything!)

6
votes

There's a task to do just what you're asking about.

You'll need to install the MSBuildCommunity tasks, found here.

Then, you can create something like this:

<PropertyGroup>
<MyAssemblyVersion>$(CCNetLabel)</MyAssemblyVersion>
</PropertyGroup>

<Target Name="GenAssemblyInfo">
    <AssemblyInfo
      ContinueOnError="false"
      CodeLanguage="CS"
      OutputFile="$(MSBuildProjectDirectory)\YourAssembly\AssemblyInfo.cs"
      AssemblyTitle="blah"
      AssemblyDescription="blah blah"
      AssemblyCompany="Anj Software, Inc."
      AssemblyProduct="Anj's Awesome App"
      AssemblyCopyright="blah blah"
      CLSCompliant="false"
      AssemblyVersion="$(MyAssemblyVersion)"
      AssemblyFileVersion="$(MyAssemblyVersion)"
     />
</Target>

Note that you can set a build number prefix in your ccnet.config file so that your assemblies will be numbered 2.1.0.x where x is the build number. That's how we do our version numbering where I work.

You'll still need to keep a default AssemblyInfo.cs file as part of each of the projects that make up your solution.

3
votes

I use powershell for this. lpath is the path to the source code, and buildnum is my buildnumber I append. That is all I actually do with this. However, it should give you enough to change or set any or all of the other fields available. I pass in lpath and I get the buildnumber from the available environment variables in CC.NET and I can use this script over and over again, just changing what I pass in on the command line in the config file. I also have one that modifies the resource files for the C++ Code if that is actually what you need to modify.

$files = Get-ChildItem $lpath -recurse -filter *AssemblyInfo.cs -name

Foreach ($file in $files)
{
    $file = $lpath + "\" + $file

    $fileObject=get-item $file

    $fileObject.Set_IsReadOnly($False)

    $sr = new-object System.IO.StreamReader( $file, [System.Text.Encoding]::GetEncoding("utf-8") ) 
    $content = $sr.ReadToEnd()
    $sr.Close()

    $content = [Regex]::Replace( $content, '(?<=\[assembly: AssemblyVersion\("[0-9].[0-9].[0-9].)[0-9]?[0-9]?[0-9]', $buildnum);
    $content = [Regex]::Replace( $content, '(?<=\[assembly: AssemblyFileVersion\("[0-9].[0-9].[0-9].)[0-9]?[0-9]?[0-9]', $buildnum);

    $sw = new-object System.IO.StreamWriter( $file, $false, [System.Text.Encoding]::GetEncoding("utf-8") )
    $sw.Write( $content )
    $sw.Close()

    $fileObject.Set_IsReadOnly($True)
}