How do I automatically set all projects in my solution to the same version?
Asked Answered
Y

4

23

I have a Visual Studio solution with 5 C# projects. I want the assembly versions to match in each project. But it looks like I have to go into each project's properties and click assembly version for each project one at a time. Is there a way to treat the solution like it just has one version as a whole that applies to each project?

Yeomanly answered 21/9, 2017 at 20:23 Comment(1)
I am still using this addin even if it doesn't support VS2017. Versioning Controlled Build You can add a custom tool and launch the addin with a command line as explained in the readme. You could use it to change and set all the Versioning information without opening each AssemblyInfo.cs in each projectEnameling
K
31

Just create a file e.g. GlobalAssemblyInfo.cs in the solution root folder then add the necessary attributes to it and finally add it as an existing item to each project as a link.

In Solution Explorer right click on the project name > Add > Existing item... and in the dialog box select Add As Link option from the dropdown list as you can see on this image.

// Content of GlobalAssemblyInfo.cs file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Please note:

  • you have to remove these attributes from each project's Properties\AssemblyInfo.cs file.
  • you can also move other assembly attributes into the GlobalAssemblyInfo.cs file as well

The result is that you will have only one file where you can set the version and it will apply to all projects.

UPDATE #1:

In .NET 5 projects an AssemblyInfo.cs file is automatically generated during build, by default.

It seems that only 7 attributes is generated automatically:

  • AssemblyCompanyAttribute
  • AssemblyProductAttribute
  • AssemblyConfigurationAttribute
  • AssemblyVersionAttribute
  • AssemblyFileVersionAttribute
  • AssemblyInformationalVersionAttribute
  • AssemblyTitleAttribute

You have two options here:

  • Disable automatic generation of AssemblyInfo.cs file.
  • Leave automatic generation of AssemblyInfo.cs file enabled and turn off generation of specific attributes.

Create a file (name: Directory.Build.props) and put it next to the .sln file so that it will be applied to all the projects within the solution.

Example #1 - Disable automatic build of AssemblyInfo.cs file

Directory.Build.props:

<Project>
  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  </PropertyGroup>
</Project>

Example #2 - Disable only specific attribute generation

In this case simply add <Generate...>false</Generate...> line to disable a specific attribute where ... is the attribute type name.

Directory.Build.props:

<Project>
  <PropertyGroup>
    <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
    <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
    <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
    <GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
  </PropertyGroup>
</Project>

Remarks

Learn more about AssemblyInfo properties in SDK-style project files.

This update applies to .NET Core versions as well.

If a specific project has special needs you can override these settings in the .csproj file as well.

As for me I usually put the attributes as follows:

  • GlobalAssemblyInfo.cs
    • AssemblyCompanyAttribute
    • AssemblyProductAttribute
    • AssemblyCopyrightAttribute
    • AssemblyConfigurationAttribute
    • AssemblyTrademarkAttribute
    • AssemblyCultureAttribute
    • AssemblyVersionAttribute
    • AssemblyFileVersionAttribute
    • AssemblyInformationalVersionAttribute
    • ComVisibleAttribute
  • AssemblyInfo.cs (in specific projects)
    • AssemblyTitleAttribute
    • AssemblyDescriptionAttribute
    • GuidAttribute
Kingbolt answered 22/9, 2017 at 0:35 Comment(9)
Hmm, when I add an existing item, it seems to make a copy. So changes to the file in the root folder aren't reflected in the copies.Yeomanly
Ah, you meant for me to use "Add as Link," didn't you?Yeomanly
Yes, I updated my answer so that it now contains this essential information as well. Thanks for your comment.Kingbolt
dotnet now appears to be creating assembly infos for library projects automatically in \obj\CONFIG\net.50\PROJECTNAME.AssemblyInfo.cs, which collides with GlobalAssemblyInfo.cs. Do you know how it should be done with .net 5?Foolhardy
@Benni, I updated my answer regarding .NET 5. Hope it helps.Kingbolt
When generating NuGet packages from an SDK-style project, it's necessary to define a Version element inside PropertyGroup within Directory.Build.props. (Also maybe Authors, Copyright, Company, and so on.) In this case, there will be two global version numbers to update on each release.Inkwell
@atomsmith, of course, you can remove version attributes from the GlobalAssemblyInfo.cs and use only the msbuild variables for versioning. Actually, for my nuget packages (with SDK-style project) I did the same.Kingbolt
@Gabor, That technique only seems to work with SDK-style projects. In my case I have a mixture of SDK and non-SDK within the same solution.Inkwell
@atomsmith, in that case you may use preprocessor directives for conditional compilation in your GlobalAssemblyInfo.cs file. In case of SDK-style projects symbols for the target framework are available, so you can check if they are defined and if not then you can include the version attributes inside an #if !NET && !NETCOREAPP ... #endif block.Kingbolt
J
5

Since MSBuild 15 Visual Studio 2017 you can use Directory.Build.targets file for this.

  1. Create Directory.Build.targets file where your .sln file is
  2. Add your version to the created file:
  <Project>
    <PropertyGroup>
        <Version>0.1.0-alpha</Version>
    </PropertyGroup>
  </Project>
  1. That's it - this will get applied to all projects in the solution.

You can do many other things with Directory.Build.props and Directory.Build.targets - more here: https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build

Jordonjorey answered 5/9, 2022 at 13:55 Comment(0)
P
4

I don't think there's any solution level option to do this. I use powershell script to achieve it for my 15 projects in a solution.

  $version= "1.3.0.0" 
  (Get-ChildItem -Include AssemblyInfo.cs -Recurse ) | 
     Foreach-Object { 
         Set-Content $_ ((Get-content $_ -Encoding UTF8) -replace "\d+\.\d+\.(\d+|\*)(\.(\d+|\*))?", $version)  -Encoding UTF8 
    }

Save this script with in same directory as your solution file. You can also add this as solution item in the solution itself and launch it from Visual studio command line option when you right click on the script file.

Permissive answered 21/9, 2017 at 20:30 Comment(0)
A
1

Since each project has its own assembly they will be treated independently. What I've found works best for me is to use a T4 template and base it on an algorithm within the template such as this where the revision is a calculation for hours since 1/1/2000:

<#@ template debug="false" hostspecific="false" language="C#" #>
using System.Reflection;
[assembly: AssemblyVersion("1.0.6.<#= this.RevisionNumber #>")]
[assembly: AssemblyFileVersion("1.0.6.<#= this.RevisionNumber #>")]
<#+
    int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(2000,1,1)).TotalHours;
#>
Arius answered 21/9, 2017 at 20:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.