Automatically update version number

我希望我的应用程序的版本属性对于每个构建都是增量的,但是我不确定如何在 Visual Studio (2005/2008)中启用这个功能。我尝试将 AssemblyVersion 指定为1.0。* but it doesn’t get me really what I want。

I'm also using a settings file and in earlier attempts when the assembly version changed my settings got reset to the default since the application looked for the settings file in another directory.

我希望能够以1.1.38的形式显示一个版本号,这样当用户发现一个问题时,我可以记录他们正在使用的版本,并告诉他们升级,如果他们有一个旧版本。

如果能简短地解释一下版本控制是如何工作的,我们将不胜感激。构建和修订的数量何时增加?

77657 次浏览

有了“内置”的东西,你不能,因为使用1.0。* or 1.0.0.* 将用编码的日期/时间戳替换修订和构建编号,这通常也是一种好方法。

有关更多信息,请参见/v 标记中的 装配链接器文档。

至于自动递增数字,请使用 AssemblyInfo Task:

AssemblyInfo Task

这可以配置为自动递增生成号。

有两个陷阱:

  1. Version 字符串中的4个数字中的每一个都被限制为65535。这是一个 Windows 限制,不太可能得到修复。
  2. 与 Subversion 一起使用需要做一个小小的更改:

检索版本号很容易:

Version v = Assembly.GetExecutingAssembly().GetName().Version;
string About = string.Format(CultureInfo.InvariantCulture, @"YourApp Version {0}.{1}.{2} (r{3})", v.Major, v.Minor, v.Build, v.Revision);

还有,澄清一下。Net 或者至少在 C # 中,build 实际上是第三个数字,而不是第四个(例如,习惯于 Major 的 Delphi 开发人员)。小事。放手。Build)可能期望。

In .net, it's Major.Minor.Build.Revision.

您使用的是什么源代码管理系统?

几乎所有这些文件都有某种形式的 $Id $tag,当文件签入时会展开该标记。

我通常使用某种形式的黑客显示这作为版本号。

另一种替代方法是使用日期作为构建号: 080803-1448

一段时间以前,我写了一个快速和肮脏的 exe,将更新的版本 # 的汇编信息。{ cs/vb }-作为构建过程的一部分,我还使用 rxfind.exe (一个简单而强大的基于正则表达式的搜索替换工具)从命令行执行更新。还有一些有用的提示:

  1. 将装配信息分为产品部件(公司名称、版本等)和装配特定部件(装配名称等)
  2. 另外-我使用 subversion,所以我发现将 build 编号设置为 subversion 修订编号很有帮助,因此总是很容易回到生成汇编的代码库(例如1.4.100.1502是从1502修订版构建的)。

NET 默认汇编版本为1.0。* 并在自动递增时使用以下逻辑: 它将构建部分设置为自2000年1月1日以来的天数,并将修订部分设置为自当地时间午夜以来的秒数除以2。看这个 MSDN 文章

汇编版本位于 Assemblyinfo.vb 或 Assembly blyinfo.cs 文件中:

' Version information for an assembly consists of the following four values:
'
'      Major Version
'      Minor Version
'      Build Number
'      Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>


<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

如果需要一个自动递增的数字,以便在每次编译完成时进行更新,则可以在预生成事件中使用 版本更新器。如果您愿意,您的预生成事件可以检查生成配置,以便版本号对于发布生成只会递增(例如)。

I have found that it works well to simply display the date of the last build using the following wherever a product version is needed:

System.IO.File.GetLastWriteTime(System.Reflection.Assembly.GetExecutingAssembly().Location).ToString("yyyy.MM.dd.HH.mm.ss")

而不是试图从下面这样的东西获得版本:

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
object[] attributes = assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyFileVersionAttribute), false);
object attribute = null;


if (attributes.Length > 0)
{
attribute = attributes[0] as System.Reflection.AssemblyFileVersionAttribute;
}

[ VisualStudio2017,。 csproj属性]

要自动更新 PackageVersion/Version/AssemblyVersion 属性(或任何其他属性) ,首先创建一个新的 Microsoft.Build.Utilities.Task类,该类将获取当前的构建号并发回更新后的编号(我建议仅为该类创建一个单独的项目)。

我手动更新 Major. small 编号,但是让 MSBuild 自动更新构建编号(1.1. 1,1.1. 2.1.1. 3,等等)

using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
using System.Text;


public class RefreshVersion : Microsoft.Build.Utilities.Task
{
[Output]
public string NewVersionString { get; set; }
public string CurrentVersionString { get; set; }


public override bool Execute()
{
Version currentVersion = new Version(CurrentVersionString ?? "1.0.0");


DateTime d = DateTime.Now;
NewVersionString = new Version(currentVersion.Major,
currentVersion.Minor, currentVersion.Build+1).ToString();
return true;
}


}

然后调用最近创建的 Task on MSBuild 进程,在. csproj 文件中添加下面的代码:

<Project Sdk="Microsoft.NET.Sdk">
...
<UsingTask TaskName="RefreshVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\<dll path>\BuildTasks.dll" />
<Target Name="RefreshVersionBuildTask" BeforeTargets="Pack" Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<RefreshVersion CurrentVersionString="$(PackageVersion)">
<Output TaskParameter="NewVersionString" PropertyName="NewVersionString" />
</RefreshVersion>
<Message Text="Updating package version number to $(NewVersionString)..." Importance="high" />
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\mustache.website.sdk.dotNET.csproj" Query="/Project/PropertyGroup/PackageVersion" Value="$(NewVersionString)" />
</Target>
...
<PropertyGroup>
..
<PackageVersion>1.1.4</PackageVersion>
..

当选择 VisualStudioPack 项目选项时(只需更改为 BeforeTargets="Build"以便在构建之前执行任务) ,RefreshVersion 代码将被触发以计算新版本号,并且 XmlPoke任务将更新您的。相应的 csproj 属性(是的,它将修改文件)。

在使用 NuGet 库时,我还通过在前面的示例中添加下一个构建任务来将包发送到 NuGet 存储库。

<Message Text="Uploading package to NuGet..." Importance="high" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)\bin\release" Command="c:\nuget\nuget push *.nupkg -Source https://www.nuget.org/api/v2/package" IgnoreExitCode="true" />

c:\nuget\nuget is where I have the NuGet client (remember to save your NuGet API key by calling nuget SetApiKey <my-api-key> or to include the key on the NuGet push call).

以防有人受益。

下面是一个手工操作的替代选项: 这是我编写的一个快速而粗糙的 PowerShell 代码片段,它是从 Jenkins 构建系统的预构建步骤中调用的。

它将 AssemblyVersionAssemblyFileVersion的最后一个数字设置为由构建系统自动设置的 BUILD_NUMBER环境变量的值。

if (Test-Path env:BUILD_NUMBER) {
Write-Host "Updating AssemblyVersion to $env:BUILD_NUMBER"


# Get the AssemblyInfo.cs
$assemblyInfo = Get-Content -Path .\MyShinyApplication\Properties\AssemblyInfo.cs


# Replace last digit of AssemblyVersion
$assemblyInfo = $assemblyInfo -replace
"^\[assembly: AssemblyVersion\(`"([0-9]+)\.([0-9]+)\.([0-9]+)\.[0-9]+`"\)]",
('[assembly: AssemblyVersion("$1.$2.$3.' + $env:BUILD_NUMBER + '")]')
Write-Host  ($assemblyInfo -match '^\[assembly: AssemblyVersion')
        

# Replace last digit of AssemblyFileVersion
$assemblyInfo = $assemblyInfo -replace
"^\[assembly: AssemblyFileVersion\(`"([0-9]+)\.([0-9]+)\.([0-9]+)\.[0-9]+`"\)]",
('[assembly: AssemblyFileVersion("$1.$2.$3.' + $env:BUILD_NUMBER + '")]')
Write-Host  ($assemblyInfo -match '^\[assembly: AssemblyFileVersion')
        

$assemblyInfo | Set-Content -Path .\MyShinyApplication\Properties\AssemblyInfo.cs -Encoding UTF8
} else {
Write-Warning "BUILD_NUMBER is not set."
}