.NET: Large revision numbers in AssemblyVersionAttribute
Asked Answered
F

6

46

We have the convention of versioning our builds as [major].[minor].[micro].[revision], e.g. 2.1.2.33546.

Our build-script automatically updates an AssemblyInfo.cs file containing

[assembly: AssemblyVersion("x.y.z.w")]

in order to embed the version-number in the assembly.

But our Subversion-repository just reached revision #65535, which broke our build.

It turns out that each number in the version-number has a maximum value of 65534 (probably due to a Windows-restriction).

Have you encountered this problem? Any good solutions/workarounds?

We like the scheme of embedding the revision-number and we obviously can't just reset our Subversion-server :-)

Frederico answered 27/7, 2009 at 13:55 Comment(0)
A
50

A bit more Background information:

Why are build numbers limited to 65535?

As this is unlikely to get changed, your options are:

  • Take the Revision Modulo 65535, which means you are back to 1
  • Use the Micro-Field in your version number to split the version number by dividing the revision by 1000. That means your version could be 1.0.65.535
  • Do not store the SVN Revision in the AssemblyVersion, but instead in the AssemblyInformationalVersion. That way your Application can still access it for display purposes, although you can't use Windows Explorer anymore to quickly check the SVN Revision
  • Do not store the SVN Revision in the AssemblyVersion, but instead in the AssemblyProduct or AssemblyDescription fields. Again, that way your Application can still access it, but also Explorer will now show it in the Property Sheet.
Acrogen answered 27/7, 2009 at 14:12 Comment(1)
If you put it in AssemblyInformationalVerison, you can see it in Windows Explorer under the property "Product Version". So that is a good option.Geographical
M
11

One option might be to just use the [AssemblyFileVersion]; this still raises a warning, but it'll build, at least:

[assembly: AssemblyFileVersion("1.0.0.80000")]
Manchester answered 27/7, 2009 at 13:59 Comment(1)
This has been fixed in later versions of msbuild(4.0), and no longer gives a warning.Briggs
C
9

We decided to use the same convention, and due to the limitations of Windows version numbers we chose to drop the "micro" part of our version numbers in order to preserve the revision number. Our version numbers are now [major].[minor].[revision / 10000].[revision % 10000], so the assemblies built from revision 65535 have the version 2.01.6.5535.

Crevasse answered 27/7, 2009 at 14:10 Comment(4)
I like that +1, how do you inject the value into the AssemblyInfo.cs?Clot
Make sure you don't make use of "minor upgrades" in windows installer if you do this (i.e. upgrade which avoids full uninstall/reinstall). Windows installer will completely ignore the 4th version component. If you no longer manually update the 3rd version component to reflect releases, windows installer may fail to update certain files.Wingspread
@Ray Hayes: Our NAnt build script uses svn info . --xml to get the revision number of the working copy, then calls a custom-written utility to output that revision into a "SolutionInfo.cs" file containing an [AssemblyVersion] attribute. This file is not added to Subversion, but is just referenced by all the projects (use "Add As Link" in VS) in the solution, so that they're all built with the latest version number.Crevasse
@wcoenen: This is a very good point, which I had forgotten. We had to use [major].[minor].[revision].0 as the version number for our MSI packages. We haven't reached revision 65,536 yet; when we do, we might just have to wrap back to 1 (and store the "high bit" in the minor field). Our minor version is currently 0, so we've got room for more information there.Crevasse
A
5

According to MSDN, the components of the AssemblyVersionAttribute version number are limited to UInt16.MaxValue - 1 by the assembly meta data, i.e. you can't store larger numbers in an assembly file. The file version, as Marc Gravell suggests, might be enough for you, depending on who will read your version number.

Arborvitae answered 27/7, 2009 at 14:3 Comment(0)
W
2

This answer is for people, who use the Azure Build Pipeline, want to insert the BuildId value as last number of the assembly version and have a problem with a too large value of the BuildId. (> 65535)

My solution is to use the last 4 or 5 digits of the BuildId, which are injected into the file AssemblyInfo.cs.
I don't use the modulo operation, because than the version number would look totally different from the BuildId (after reaching the limit). Instead in my solution the "shorted" version looks similar to the BuildId.

Examples:

The AssemblyVersion is 1.0.0.0 and the BuildId is 333.
--> The new AssemblyVersion becomes 1.0.0.333. (Small number, no problem.)

The AssemblyVersion is 1.0.0.0 and the BuildId is 55555.
--> The new AssemblyVersion becomes 1.0.0.55555. (Still in range.)

The AssemblyVersion is 1.0.0.0 and the BuildId is 66666.
--> The new AssemblyVersion becomes 1.0.0.6666. (Uses last 4 digits. More isn't possible.)

The AssemblyVersion is 1.0.0.0 and the BuildId is 111111.
--> The new AssemblyVersion becomes 1.0.0.11111. (Uses last 5 digits.)

Easy usage by following steps

Step 1: Define the variable shortBuildId in your pipeline by this snippet.

variables:
- name: shortBuildId # note: The last 4 or 5 digits of the BuildId, because for the assembly version number the maximum value is 65535
  value: '[not set]' # will be set by powershell script

Alternatively you could define it like this. It depends on the style how you did define your already existing variables.

variables:
  shortBuildId: '[not set]'

Step 2: Insert these tasks above the existing tasks.

The first task creates the short BuildId and saves it to variable shortBuildId.

The second task updates the 4th version field in the file AssemblyInfo.cs. So the short buildId is injected into both, the AssemblyVersion and the AssemblyFileVersion.

Note: In this file you need an assembly version with 4 numbers (e.g. 1.0.0.0). If you have only 3 numbers (e.g. 1.0.0) it will not work.

- task: PowerShell@2
  displayName: Define short build ID
  # If allowed, use the last 5 digits. If they are larger than 65000, use the last 4 digits. Leading zeros are removed.
  # This is needed, because the full build ID can't be used as number for the assembly version.
  inputs:
    targetType: 'inline'
    script: |
      $shortId = $env:BUILD_BUILDID
      $shortId = $shortId % 100000
      if ($shortId -gt 65000) { $shortId = $shortId % 10000 }
      Write-Host "Build ID: $env:BUILD_BUILDID --> $shortId"
      Write-Host "##vso[task.setvariable variable=shortBuildId]$shortId" 
    showWarnings: true

- task: RegexReplace@3
  displayName: Insert shortBuildId into AssemblyInfo:
    InputSearchPattern: 'myProjectDirectory\Properties\AssemblyInfo.cs'
    FindRegex: '(\[assembly: (AssemblyVersion|AssemblyFileVersion)\("\d+\.\d+\.[0-9*]+)\.[0-9*]+("\)\])'
    ReplaceRegex: '$1.$(shortBuildId)$3'
    UseUTF8: true
    UseRAW: true

Step 3: Adjust the path in the second task related to your project.

Edit the value of InputSearchPattern.
If you want to insert the shortBuildId into all projects of your solution, just write InputSearchPattern: '**\AssemblyInfo.cs'

Credit

Thanks to Dr. Edmund Weitz for his great tool The Regex Coach, which is free to use.

Womanly answered 5/1, 2022 at 17:55 Comment(0)
U
0

I'd like to propose by way of answer the following scheme for anyone using semver/gitflow:

AssemblyVersionAttribute SemVer/Gitflow
Major Version Major
Minor Version Minor
Build Number Patch
Revision Gitflow ID

Where "Gitflow ID" is a digit followed by 0000 - 9999, per the following:

Gitflow ID Branch
00000 - 09999 Release (alpha)
10000 - 19999 Release (beta)
20000 - 29999 Release (RC)
30000 - 65535 Development

The intuition behind 00000 - 29999 is that these numbers represent something of a logical negative pre-release number, 30000 represents logical zero, and 30001 - 65535 represent logical positive. More formally, this is a kind of 10's complement representation, with offset K = 30000.

So for example:

  1. Topic branch feature/A starts at 0.0.0.30000
  2. Simultaneously, topic branch feature/B also starts at 0.0.0.30000
  3. feature/B merges to dev at 0.0.0.31000 while feature/A is at 0.0.0.30021
  4. feature/A merges updates from dev at 0.0.0.31001
  5. feature/A merges to dev at 0.0.0.32000
  6. v1.0-alpha.1 release starts from dev at 1.0.0.00001
  7. v1.0-rc.3 at 1.0.0.20002
  8. Finally v1.0 released to Master at 1.0.0.30000
  9. Hotfix v1.0.1 applied at 1.0.1.30000
  10. Meanwhile v1.1 development continuing at 1.0.1.30002

The above suggests that the development range 30000-65535 could be further subdivided for topic branches, i.e. DDTTT, with DD ranging from 30 to 65 (max 65 - 30 + 1 = 36 dev PRs until release). Alternatively, the whole range could be used for development and topic branches without distinction; in this case, merging from dev to topic would have topic be dev + 1 and vice-versa. Either case allows there to be multiple identical version numbers at the topic branch level, but only a single version number for any dev commit. The DDTTT arrangement makes it clearer which version number represents a dev commit (e.g. 57000) at the expense of limiting the number of dev commits in a release. However, assuming a frequent enough release cadence, this should not be a problem. At any rate, production releases are clearly seen as having gitflow IDs of 30000.

Unmindful answered 16/6, 2022 at 17:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.