I think most people probably know how to version C# projects by now, but for my own future reference here is how I'm currently doing it.
In my project's csproj file I append the following VersionProject target to the BuildDependsOn project. You could override the BeforeBuild target, but appending a dependent target is safer according to Sayed Hashimi. The following goes directly into each of my csproj files:
<PropertyGroup>
<SourceDirectory>$(MSBuildProjectDirectory)\..\..\..</SourceDirectory>
<ProjectDirectory>$(MSBuildProjectDirectory)</ProjectDirectory>
</PropertyGroup>
<Import Project="$(SourceDirectory)\utils\global.targets" />
<PropertyGroup>
<BuildDependsOn>
VersionProject;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
The VersionProject target is a custom target in my global.targets MSBuild project file which gets included into my csproj file. This target is using the MSBuild community tasks' AssemblyInfo task.
<Target Name="VersionProject">
<Message Text="Generating AssemblyInfo.cs Version: $(BuildVersion)"/>
<MakeDir
Directories="$(ProjectDirectory)\Properties"
Condition="!Exists('$(ProjectDirectory)\Properties')" />
<AssemblyInfo CodeLanguage="CS"
OutputFile="$(ProjectDirectory)\Properties\AssemblyInfo.cs"
AssemblyCompany="$(CompanyName)"
AssemblyProduct="$(ProductName)"
AssemblyCopyright="$(Copyright)"
AssemblyVersion="$(BuildVersion)"
AssemblyFileVersion="$(BuildVersion)"
AssemblyTitle="$(ProductName)"
AssemblyDescription="$(ProductName)"/>
</Target>
The great thing about this, I can reuse this target over and over again for each of my projects. Some properties like the BuildVersion are set when running under CC.NET, others like CompanyName, Copyright are set once in the global.targets file as these don't change between projects. By default my global.targets file will default the ProductName to the MSBuild project file name (minus the file extension), this of course can be overridden in any number of ways - including from CC.NET.
The nice thing is, this will work when building from the command line with MSBuild.exe or from within Visual Studio. This last point is important because we don't ever checkin the AssemblyInfo.cs source files to SVN (we set SVN ignore on these since they are autogenerated on every build) and most developers would like to checkout, open the solution, and finally CTRL SHIFT B. Some OSS projects I've worked on require you to build from the command line first (to generate the AssemblyInfo.cs files) before you can build from Visual Studio; I believe this tends to confuse most .NET developers since most are so IDE dependant.
Another thing to note is that if a developer wanted to build a specifically versioned project from within Visual Studio all they would need to do would be to set an environment variable before starting Visual Studio, specifically: BUILDVERSION=1.0.0.1503.