自动更新版本号。

115

我希望我的应用程序的版本属性在每次构建时都能自动增加,但我不确定如何在 Visual Studio (2005/2008) 中启用此功能。我试过将 AssemblyVersion 指定为 1.0.*,但它并没有完全达到我的要求。

我还使用了一个设置文件,在之前的尝试中,当程序集版本更改时,我的设置会重置为默认设置,因为应用程序会在另一个目录中查找设置文件。

我想能够显示形如 1.1.38 的版本号,这样当用户发现问题时,我就可以记录他们使用的版本,并告诉他们升级到新版本。

如果能简要解释一下版本控制的原理就更好了。构建号和修订号是在什么时候增加的呢?


以下问题有一个简单方便的解决方案,可以通过在构建事件中生成源文件来将构建号注入到您的应用程序中。https://dev59.com/KG855IYBdhLWcg3wQx5L - Ashley Davis
可能是使用Visual Studio时,我可以自动增加文件构建版本吗?的重复问题。 - Michael Freidgeim
8个回答

98

使用“内置”方法,您不能使用1.0.*或者1.0.0.*来替换版本号和构建号,而应该用一个编码的日期/时间戳替换它们,这通常也是一个不错的方法。

有关更多信息,请参见/v标签中的Assembly Linker文档。

至于自动递增数量,请使用AssemblyInfo任务:

AssemblyInfo 任务

这可以配置为自动递增版本号。

有两个要注意的问题:

  1. 版本字符串中的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#中,版本构建号实际上是第三个数字,而不是某些人(例如习惯于Major.Minor.Release.Build的Delphi开发人员)可能期望的第四个数字。

在.NET中,它是Major.Minor.Build.Revision。


3
我刚刚发现了一个类似的Visual Studio插件:http://autobuildversion.codeplex.com/ 。 - jrsconfitto
6
这是否意味着,在2179年6月4日(自2000年以来的第65536天),微软的默认版本号将出现问题? - Lloyd Powell
1
@Jugglingnutcase - 如果它适用于当前版本的Visual Studio,那么该链接将近乎完美。 - Kraang Prime
2
@SanuelJackson 哈哈!是啊,那会儿就好了。可惜我没有跟上2010年的评论,抱歉!:P 时间和版本的进展让我们所有人都感到悲伤。 - jrsconfitto
@Michael Stum:您能否更新您的答案中**AssemblyInfo Task**的链接?对我来说,它无法正确加载。 - Matt

21

VS.NET默认程序集版本为1.0.*,并在自动增量时使用以下逻辑:将构建部分设置为自2000年1月1日以来的天数,并将修订部分设置为当地时间午夜后的秒数除以二。请参见此MSDN文章

程序集版本位于assemblyinfo.vb或assemblyinfo.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")> 

感谢您包含初始日期:“2000年1月1日”。 - kiewic

12

我发现在需要产品版本的任何地方,只需简单地显示最后构建日期即可:

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;
}

7
我认为你的意思是:yyyy.MM.dd.HHmm 而不是 yyyy.MM.dd.HHMM。 - JHubbard80
1
这是将某种版本号附加到程序集文件更改的最简单解决方案。 - Alexei - check Codidact

6

[Visual Studio 2017, .csproj 属性]

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

我手动更新主版本和次版本号,但让 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;
    }

}

然后在你的 .csproj 文件中添加以下代码,调用最近创建的 Task 并运行 MSBuild 进程:

<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>
 ..

当选择Visual Studio Pack项目选项(只需更改为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 是我安装 NuGet 客户端的路径(记得通过调用 nuget SetApiKey <my-api-key> 命令来保存你的 NuGet API 密钥,或者在 NuGet 推送时包含密钥)。

希望这能帮到有需要的人 ^_^。


5
你们使用的是哪种源代码管理系统?
几乎所有的系统都有一些形式的 $ Id $ 标签,当文件被检入时会被扩展。
我通常使用某种技巧将其显示为版本号。
另一个选择是使用日期作为构建号:080803-1448。

你能详细说明一下“几乎所有的文件都有某种形式的$ Id $标签,在文件被检入时会被扩展”的意思吗?具体来说,您是否知道这适用于Subversion吗? - Greg B

1

前段时间我写了一个快速而简单的exe程序,用于更新assemblyinfo.{cs/vb}中的版本号 - 我还使用了rxfind.exe(一个基于正则表达式的简单而强大的搜索替换工具)来作为构建过程的一部分从命令行进行更新。另外还有一些有用的提示:

  1. 将assemblyinfo分成产品部分(公司名称、版本等)和程序集特定部分(程序集名称等)。请参见此处
  2. 此外 - 我使用subversion,因此我发现将构建号设置为subversion修订号非常有帮助,从而使得始终可以轻松地返回生成程序集的代码库(例如1.4.100.1502是从修订号1502构建的)。

如果是针对代码文件(*.cs/*.vb),你应该使用 T4 模板。 - BrainSlugs83

0
如果您想要一个自动递增的数字,每次编译时都会更新,您可以在预构建事件中使用VersionUpdater。如果您愿意,您的预构建事件可以检查构建配置,以便版本号仅在发布构建(例如)中递增。

有趣。我自己已经有了同名的东西好几年了,但不知道还有这样一个存在(尽管我最近才把它放到网上):https://github.com/rjamesnw/VersionUpdater - James Wilkins

0
这里有一个手摇替代方案:这是我编写的一个快速且简单的 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."
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接