'Specify assembly version number as a command line argument in MSBuild
I would like to be able to specify the version number for all assemblies to be generated during a build as a MSBuild command argument like this:
MSBuild.exe /p:version=5.4.3.0
I have looked over AssemblyInfoTask
but it does not seem to me like a good solution in this case.
Solution 1:[1]
I use the AssemblyInfo task as you describe in your comment all the time.
<!-- update standard assembly attribute in all projects -->
<Target Name="BeforeBuild" >
<Message Text="Updating AssemblyInfo to Version $(VersionNumber)"></Message>
<Message Text="Writing to AssemblyInfo files in $(SolutionRoot)"></Message>
<AssemblyInfo AssemblyInfoFiles="@(AssemblyInfoFiles)"
AssemblyCopyright="$(AssemblyCopyright)"
AssemblyVersion="$(VersionNumber)"
AssemblyFileVersion="$(VersionNumber)"
>
</AssemblyInfo>
</Target>
The VersionNumber value is passed from outside the MSBuild project file exactly as you describe:
MSBuild <project_file> /p:VersionNumber=<value>;...
We use the BeforeBuild target to ensure the AssemblyInfo.cs files all get worked on before the build starts. Is this not what you want?
Solution 2:[2]
For SDK-style projects that are built using dotnet.exe
, assembly version attributes are generated automatically, so you can use /p:Version=5.4.3.0
right out of the box.
If you use the old project format, you need to add the following BeforeBuild
step to your .csproj
file. No need to use extra .targets
and extension packs, because MSBuild already has a nice built-in task which does most of the stuff:
<Target Name="BeforeBuild">
<ItemGroup>
<AssemblyAttributes Include="AssemblyVersion">
<_Parameter1>$(Version)</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<MakeDir Directories="$(IntermediateOutputPath)" />
<WriteCodeFragment Language="C#"
OutputFile="$(IntermediateOutputPath)Version.cs"
AssemblyAttributes="@(AssemblyAttributes)" />
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)Version.cs" />
</ItemGroup>
</Target>
Just make sure you remove the existing AssemblyVersion
attribute because it will now be generated during build.
Update 7/29/2020:
Michael Parker has pointed out that if you use this approach and do a build from Visual Studio, you end up with an empty version in the Version.cs
file. To overcome this, I suggest defining the default Version value in your .csproj
or Directory.Build.props
file as follows:
<PropertyGroup>
...
<Version Condition="'$(Version)' == ''">1.0.0.0</Version>
</PropertyGroup>
This will set it to 1.0.0.0
if Version wasn't specified in the command line.
Solution 3:[3]
I know this is an old question but Google leads me to here as top result.
I followed a simple solution in this. No need for extension pack.
Basically what you need to do is add a "BuildCommon.targets" files and modify your csproj file accordingly to have the version number specified in msbuild like:
msbuild.exe abc.sln /p:Configuration=Release;VersionAssembly=1.2.3.4
Hope this helps.
Solution 4:[4]
The top answer is great, but I needed to make a few adjustments. We have a solution containing a mix of SDK and non-SDK projects. Further we also use AspNetCompileMerge
for pre-compiling ASP.NET MVC 5 views. Using the property name AssemblyAttributes
causes the target of GenerateAssemblyInfo
from AspNetCompileMerge.targets
to be executed and failing. So I finally arrived on the following target that is shared by the whole solution through Directory.Build.props
:
<PropertyGroup>
<Version Condition="'$(Version)' == ''">1.0.0.0</Version>
<AssemblyVersion Condition="'$(AssemblyVersion)' == ''">$(Version.Split('-')[0])</AssemblyVersion>
<FileVersion Condition="'$(FileVersion)' == ''">$(Version.Split('-')[0])</FileVersion>
<InformationalVersion Condition="'$(InformationalVersion)' == ''">$(Version)</InformationalVersion>
</PropertyGroup>
<Target Name="NonSdkGenerateAssemblyInfo" DependsOnTargets="PrepareForBuild" BeforeTargets="BeforeBuild" Condition="('$(UsingMicrosoftNETSdk)' != 'True' And '$(GenerateAssemblyInfo)' != 'False')">
<ItemGroup>
<NonSdkAssemblyAttributes Include="AssemblyVersion">
<_Parameter1>$(AssemblyVersion)</_Parameter1>
</NonSdkAssemblyAttributes>
<NonSdkAssemblyAttributes Include="AssemblyFileVersion">
<_Parameter1>$(FileVersion)</_Parameter1>
</NonSdkAssemblyAttributes>
<NonSdkAssemblyAttributes Include="AssemblyInformationalVersion">
<_Parameter1>$(InformationalVersion)</_Parameter1>
</NonSdkAssemblyAttributes>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="@(NonSdkAssemblyAttributes)"
Language="C#"
OutputDirectory="$(IntermediateOutputPath)"
OutputFile="AssemblyInfo.cs">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>
You can add additional attributes if needed. The default version number is 1.0.0.0
and you can specify additional version numbers on the command line, mimicking SDK-behaviour:
AssemblyVersion
andFileVersion
default to the value of$(Version)
without the suffix. For example, if$(Version)
is1.2.3-beta.4
, then the value would be1.2.3
.InformationalVersion
defaults to the value of$(Version)
.
Solution 5:[5]
The top answer is indeed good. In addition here's a couple of clarifications/suggestions that might prove useful (and perhaps obvious from the above postings) to avoid any custom targets, BeforeBuild, etc.
- For SDK projects (i.e. no AssemblyInfo.cs):
/p:Version='1.0.0-patch'
will also work for msbuild.exe (and dotnet.exe of course) without any csproj changes. Useful for example when targetting v3 Wix setup projects that still don't support dotnet.exe. Plus you can assign $AssemblyVersion and $FileVersion to empty values since $Version will assign them automatically. - For non-SDK projects, instead of modifying csproj with custom targets, BeforeBuild, etc then it might just be simpler/quicker to upgrade them to SDK style projects, i.e. remove the obsolete AssemblyInfo.cs usage. Refer migrating projects.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | DaveE |
Solution 2 | |
Solution 3 | Jach |
Solution 4 | Bouke |
Solution 5 | stoj |