Reputation: 4231
In a C# project, we increment versions manually and have a top-level file MyAssemblyInfo.cs
containing
[assembly: AssemblyVersion("31.1.13")]
[assembly: AssemblyFileVersion("31.1.13")]
[assembly: AssemblyInformationalVersion("31.1.13-V1.0.0")]
I'd like to avoid repeating the version. For example, with the C preprocessor, one could write this as
#define VERSION "31.1.13"
[assembly: AssemblyVersion(VERSION)]
[assembly: AssemblyFileVersion(VERSION)]
[assembly: AssemblyInformationalVersion(VERSION "-V1.0.0")]
Is there a way to achieve this in C# without using any external tools?
Upvotes: 2
Views: 503
Reputation: 12749
The short answer to your question is no you cannot use pre-processor directives in this manner. One work-around is stated in the other answer and involves defining a constant. This would be perhaps the only solution for old-style projects.
If you are using the SDK-style project format however, AssemblyInfo
attributes can be set in the project file. The following properties correspond to the attributes defined above:
InformationalVersion
-> AssemblyInformationalAttribute
AssemblyVersion
-> AssemblyVersion
FileVersion
-> AssemblyFileVersion
Version
-> Can map to any/all of the above if they are omitted
All other Assembly attributes can be set via properties so long as GenerateAssemblyInfo
is true
. This requires you to remove your AssemblyInfo.cs
file to prevent duplication of those attributes.*
The way I have typically solved this is to define my own set of version-related properties in my project file (see notes below for why). For example, you might have the following:
<PropertyGroup>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<BaseVersion>31.1.13</BaseVersion>
<InfoSuffix>v1.0.0</InfoSuffix>
</PropertyGroup>
<PropertyGroup>
<!-- note: "-v1" is invalid in an Assembly Version; I assumed you meant this on the Informational one -->
<InformationalVersion>$(BaseVersion)-$(InfoSuffix)</InformationalVersion>
<AssemblyVersion>$(BaseVersion)</AssemblyVersion>
<FileVersion>$(BaseVersion)</FileVersion>
</PropertyGroup>
You could pass any of these properties on the command line to MSBuild or dotnet build if you wanted to explicitly override them:
dotnet build -p:InfoSuffix=v2.0+1234
# alternatively, specify the MSBuild properties directly
dotnet build -p:FileVersion=1.2.3.4 -p:InformationalVersion=5.6.7.8
If you have multiple projects you could set all of these properties inside of a Directory.Build.props
file so that they apply to all of your projects at once.
Some Notes
First, if you are using the Directory.Build.props
mechanism and running any sort of post-processing tasks or something like SourceLink (which appends info to the Informational version) you will need to move the second property group into a Directory.Build.targets
file instead. You'd also need to do this if you wanted to pass the properties explicitly to other tooling, such as dotnet pack
.
Second, MSBuild has a series of other version-related properties**. These include (but are not limited to):
SourceRevisionId
- appended to the Informational version (our InfoSuffix
)VersionPrefix
- A Base versionVersionSuffix
- Sets prerelease labelPackageVersion
- generates nuget versionYou can use these in combination with those specified above instead. You can even pass them as properties on the command-line if you wanted to override the values in the project/props/targets files.
Now you might wonder why I bother defining my own properties instead of using the built-in ones. The reason is that MSBuild has some strange and sometimes unexpected behavior depending on how combinations of these properties are set. Anecdotally, I noticed different behavior depending on which values I was setting and whether I was building in VS, on the command line, or using dotnet pack. It is because of this I prefer defining my own properties and then using them to explicitly set the others. It also allowed me to use conditional MSBuild logic to set certain parts of the version easier. Though I do admit, your mileage may vary.
* If you want to keep the AssemblyInfo.cs file for other attributes, you'd have to disable their automatic generation by leveraging the individual GenerateX
MSBuild properties.
** For a good explanation of some of these properties, see this blog post.
Upvotes: 1
Reputation: 474
[assembly: AssemblyFileVersion(AppVersion.Version)]
[assembly: AssemblyInformationalVersion(AppVersion.Version)]
// you can use + here but the format you use shows as invalid version for me
[assembly: AssemblyVersion(AppVersion.Version)]
// this must be at the end of the global declarations
internal class AppVersion
{
public const string Version = "31.1.13";
}
Upvotes: 5