How can I change AssemblyProduct, AssemblyTitle using MSBuild?

28,023

Solution 1

You're on the right track with the MSBuild Extension Pack.

I find the easiest way to conditionally generate the assembly details at build time is to add an "AssemblyVersion" target directly to my .csproj file(s) that require an updated AssemblyInfo file. You can add the target directly to each csproj file that requires an updated AssemblyInfo file, or as I prefer to do it, create a custom targets file with the AssemblyVersion target and have each csproj file include your custom targets file.

Either way you likely want to use the MSBuild Extension Pack or the MSBuild Community Tasks to use their respective AssemblyInfo task.

Here's some code from our build scripts:

<!-- Import the AssemblyInfo task -->
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets"/>

<!-- Overriding the Microsoft.CSharp.targets target dependency chain -->
<!-- Call our custom AssemblyVersion target before build, even from VS -->
<PropertyGroup>
    <BuildDependsOn>
        AssemblyVersion;
        $(BuildDependsOn)
    </BuildDependsOn>
</PropertyGroup>

<ItemGroup>
    <AssemblyVersionFiles Include="$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs"/>
</ItemGroup>

<Target Name="AssemblyVersion"
                Inputs="@(AssemblyVersionFiles)"
                Outputs="UpdatedAssemblyVersionFiles">
    <Attrib Files="%(AssemblyVersionFiles.FullPath)"
                    Normal="true"/>
    <AssemblyInfo
        CodeLanguage="CS"
        OutputFile="%(AssemblyVersionFiles.FullPath)"
        AssemblyCompany="$(CompanyName)"
        AssemblyCopyright="Copyright $(CompanyName), All rights reserved."
        AssemblyVersion="$(Version)"
        AssemblyFileVersion="$(Version)">
        <Output TaskParameter="OutputFile"
                        ItemName="UpdatedAssemblyVersionFiles"/>
    </AssemblyInfo>
</Target>

Solution 2

Sneal's answer was very helpful, but I'd like to show what I actually ended up doing. Instead of editing csproj files (there are several) I instead added tasks to my build script. Here's a snippet:

    <PropertyGroup>  
        <ProductName>MyApp</ProductName>
        <CompanyName>MyCompany</CompanyName>
        <Major>1</Major>
        <Minor>0</Minor>
        <Build>0</Build>
        <Revision>0</Revision>
    </PropertyGroup> 

    <ItemGroup>
        <AssemblyVersionFiles Include="..\MyMainProject\Properties\AssemblyInfo.cs"/>
    </ItemGroup>

<Target Name="AssemblyVersionMAIN" Inputs="@(AssemblyVersionFiles)" Outputs="UpdatedAssemblyVersionFiles">
        <Attrib Files="%(AssemblyVersionFiles.FullPath)" Normal="true"/>
        <AssemblyInfo
            CodeLanguage="CS"
            OutputFile="%(AssemblyVersionFiles.FullPath)"
            AssemblyProduct="$(ProductName)"
            AssemblyTitle="$(ProductName)"
            AssemblyCompany="$(CompanyName)"
            AssemblyCopyright="© $(CompanyName) 2010"
            AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
            AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)"
            AssemblyInformationalVersion="$(Major).$(Minor).$(Build).$(Revision)">
            <Output TaskParameter="OutputFile" ItemName="UpdatedAssemblyVersionFiles"/>
        </AssemblyInfo>
    </Target>

 <Target Name="Compile" DependsOnTargets="AssemblyVersionMAIN">
      <MSBuild Projects="..\MySolution.sln"     
               Properties="Configuration=Release;Platform=x86;Optimize=true" />
 </Target>

Then, I can override my variables from the command line, or a batch script, like so:

set MAJ=1
set MIN=2
set BLD=3
set REV=4

msbuild buildScript.xml /t:Compile /p:Major=%MAJ% /p:Minor=%MIN% /p:Build=%BLD% /p:Revision=%REV%
Share:
28,023

Related videos on Youtube

Charlie Salts
Author by

Charlie Salts

Just a simple programmer :)

Updated on July 09, 2022

Comments

  • Charlie Salts
    Charlie Salts almost 2 years

    I have an MSBuild script which compiles my existing solution but I'd like to change some properties of one of the projects within the solution at compile-time, including but not limited to AssemblyProduct and AssemblyTitle.

    Here's a snippet of my build script:

      <Target Name="Compile" >
     <MSBuild Projects="..\MySolution.sln" 
                 Properties="Configuration=MyReleaseConfig;Platform=x86" />
      </Target>
    

    I've got one main executable and several DLLs that are compiled. I am aware of the MSBuild Extension Pack and I suspect it might help me to get to where I need to be, although I'm not sure how to proceed.

    Can I selectively change AssemblyInfo properties at build time?

    • Raheel Khan
      Raheel Khan almost 11 years
      Out of curiosity, why would you want to do that? I'd be interested in getting to know a real-world scenario.
    • Charlie Salts
      Charlie Salts almost 11 years
      @RaheelKhan: Automated build scripts outside of Visual Studio. Such a script sets a specific version number, performs a build, generates an installer, and optionally uploads the finished installer (complete with product name and version number in the filename) to the Internet. If you have 12 variants of the same product (each with a different product name) that you update every few days, having a one-click solution for each is the way to go. Consider too that running such a script can be done by someone who isn't a programmer.
    • Raheel Khan
      Raheel Khan almost 11 years
      Thank you for that insight.
  • Charlie Salts
    Charlie Salts over 13 years
    Hmmm.. this looks like what I need. I'll try to give it a go.
  • Hovis Biddle
    Hovis Biddle almost 10 years
    Overiding the target dependency chain added some noise in VS, every time I build it asks if I want to load the updated AssemblyInfo.cs file which is kind of annoying. As a workaround, I used <Target Name="BeforeBuild"><CallTarget targets="AssemblyVersion" /></Target> instead. As expected, the alerts went away in VS and MSBuild on the CLI still picks up the changes. Great!
  • makhdumi
    makhdumi about 9 years
    Thank you for the great answer. I recommend against modifying the dependency chain for Build, however, since BeforeBuild is there for that (or if you want, you can do BeforeTargets="BeforeBuild"). Also, the Inputs and Outputs attributes aren't quite used correctly - those attributes are used to check if the Target should be run or not (might as well leave it empty for this one), so you might get behaviour where it isn't run at times. Again, thanks for the perfect solution!
  • DRapp
    DRapp about 8 years
    Very interesting... thanks as command line build is directly what I am working with too.