wormiii
wormiii

Reputation: 167

Customizations on MSBuild (like version) for a C# solution

I'm thinking that the final result is going to be "it can't be that easily done", but just seems like it should be. I have a personal project I am working on. I'd hate to have to manually (or even in script) change versions, company, copyright, and all that on ALL the assembly.cs files and would like all that to be either in a script or in a file I can change (so the script stays the same mostly) when I want to update the version. But it seems like MSBuild is mostly a "build as is specified in Visual Studio". I'd just hate to have all that history of these files where I change just the version and possibly even make a mistake as this project will continue to get bigger and bigger. I'd like to just be able to add a new project to Visual studio and have whatever command line in my powershell script just say "compile this, but give it this company name and this file version instead of whatever is listed in the code file".

Google has NOT proven fruitful in this. I've even found it difficult to build my files to a specific folder. I've had to so far make sure all my projects are 2 folders deep and was able to say to build them at ....\, but I would like to be able to change that randomly if I like and have them built elsewhere if I so desire.

Is MSBuild perhaps not the way to go? Is there someway else to build visual studio that would be better from command line? Eventually I also want to auto build the install with wix and be able to match its version with the binary versions.

thank you

Upvotes: 1

Views: 365

Answers (1)

granadaCoder
granadaCoder

Reputation: 27904

Since csproj is xml, you can use XmlUpdate "helpers" to modify the values inside the csproj file before you do your build.

For other files, you can use some other Tasks to do the job.

Here is one helpful target:

http://msbuildtasks.tigris.org/ and/or https://github.com/loresoft/msbuildtasks has the ( FileUpdate (and SvnVersion task if that is your Source-Control) ) tasks.

<Target Name="BeforeBuild_VersionTagIt_Target">

    <ItemGroup>
        <AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
    </ItemGroup>

    <!--
    <SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
        <Output TaskParameter="Revision" PropertyName="MyRevision" />
    </SvnVersion>
    -->

    <PropertyGroup>
        <MyRevision>9999</MyRevision>
    </PropertyGroup>    


    <FileUpdate Files="@(AssemblyInfoFiles)"
            Regex="AssemblyFileVersion\(&quot;(\d+)\.(\d+)\.(\d+)\.(\d+)"
            ReplacementText="AssemblyFileVersion(&quot;$1.$2.$3.$(MyRevision)" />

</Target>

Below is an example of manipulating the csproj(xml).

How to add a linked file to a csproj file with MSBuild. (3.5 Framework)

But basically, when you build, you can put all the repetative stuff in a msbuild definition file (usually with the extension .proj or .msbuild)...and call msbuild.exe MyFile.proj.

Inside the .proj file, you will reference your .sln file.

For example:

$(WorkingCheckout) would be a variable (not defined here)...that has the directory where you got a copy of hte code from your source-control.

  <Target Name="BuildIt" >
    <MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
      <Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"></Output>
    </MSBuild>
    <Message Text="BuildItUp completed" />
  </Target>

So below is the more complete example. You would save this as "MyBuild.proj" and then call

"msbuild.exe" "MyBuild.proj".

Start .proj code. (Note, I did not import the libraries for the FileUpdate Task)

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
  <PropertyGroup>
    <!-- Always declare some kind of "base directory" and then work off of that in the majority of cases  -->
    <WorkingCheckout>.</WorkingCheckout>
  </PropertyGroup>

  <Target Name="AllTargetsWrapped">


    <CallTarget Targets="BeforeBuild_VersionTagIt_Target" />
    <CallTarget Targets="BuildItUp" />

  </Target>


  <Target Name="BuildItUp" >
    <MSBuild Projects="$(WorkingCheckout)\MySolution.sln" Targets="Build" Properties="Configuration=$(Configuration)">
      <Output TaskParameter="TargetOutputs" ItemName="TargetOutputsItemName"></Output>
    </MSBuild>
    <Message Text="BuildItUp completed" />
  </Target>


<Target Name="BeforeBuild_VersionTagIt_Target">

    <ItemGroup>
        <AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
    </ItemGroup>

    <!--
    <SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
        <Output TaskParameter="Revision" PropertyName="MyRevision" />
    </SvnVersion>
    -->

    <PropertyGroup>
        <MyRevision>9999</MyRevision>
    </PropertyGroup>    


    <FileUpdate Files="@(AssemblyInfoFiles)"
            Regex="AssemblyFileVersion\(&quot;(\d+)\.(\d+)\.(\d+)\.(\d+)"
            ReplacementText="AssemblyFileVersion(&quot;$1.$2.$3.$(MyRevision)" />

</Target>



</Project>

To enhance the above, you would create a new target that would run before "BeforeBuild_VersionTagIt_Target", that would pull your code from source-control and put it in the $(WorkingCheckout) folder.

The basic steps would then be: 1. Checkout code from Source-Control. 2. Run the targets that alter the AssemblyVersion (and whatever else you want to manipulate) and 3. Build the .sln file.

That's the basics of a .proj file. You can do much more. Usually by using helper libraries that already exists.

Upvotes: 2

Related Questions