如何有一个自动递增的版本号(Visual Studio)?

我想存储一组在构建时自动递增的整数:

int MajorVersion = 0;
int MinorVersion = 1;
int Revision = 92;

编译时,它会自动递增Revision。当我构建安装项目时,它会增加MinorVersion(我可以手动这样做)。MajorVersion只能手动递增。

然后我可以在菜单Help/About中显示一个版本号给用户:

Version: 0.1.92

如何实现这一目标?

这个问题不仅问如何有一个自动递增的版本号,还问如何在代码中使用它,这是一个比其他问题更完整的答案。

443930 次浏览

使用AssemblyInfo.cs

在App_Code中创建文件,并填写以下内容或使用谷歌获取其他属性/属性。

AssemblyInfo.cs

using System.Reflection;


[assembly: AssemblyDescription("Very useful stuff here.")]
[assembly: AssemblyCompany("companyname")]
[assembly: AssemblyCopyright("Copyright © me 2009")]
[assembly: AssemblyProduct("NeatProduct")]
[assembly: AssemblyVersion("1.1.*")]

AssemblyVersion是您真正需要的部分。

然后如果你在一个网站上工作,在任何aspx页面,或控件,你可以在< page >标签,如下:

CompilerOptions="<folderpath>\App_Code\AssemblyInfo.cs"

(替换文件夹路径与适当的变量当然)。

我认为你不需要以任何方式为其他类添加编译器选项;App_Code中的所有文件在编译时都应该收到版本信息。

希望这能有所帮助。

如果你在你的项目中添加一个AssemblyInfo类,并修改AssemblyVersion属性以星号结尾,例如:

[assembly: AssemblyVersion("2.10.*")]

Visual studio将根据这些规则为你增加最终的数字(谢谢galets,我完全错了!)

要在代码中引用此版本,以便将其显示给用户,可以使用reflection。例如,

Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
DateTime buildDate = new DateTime(2000, 1, 1)
.AddDays(version.Build).AddSeconds(version.Revision * 2);
string displayableVersion = $"{version} ({buildDate})";

你应该知道三个重要的陷阱

从@ashes999:

同样值得注意的是,如果同时指定了AssemblyVersionAssemblyFileVersion,你将不会在你的.exe上看到这个。

从@BrainSlugs83:

只将第4个数字设置为*可能是不好的,因为版本并不总是递增。 第三个数字是2000年以来的天数,和第四个数字是从午夜开始的秒数(除以2)[它不是随机的]。因此,如果您在某一天晚些时候构建解决方案,而在第二天早些时候构建解决方案,那么晚些时候构建的版本号将较早。我建议总是使用X.Y.*而不是X.Y.Z.*,因为你的版本号总是这样增加。

新版本的Visual Studio会给出这样的错误:

(这个帖子开始于2009年)

指定的版本字符串包含与确定性不兼容的通配符。要么从版本字符串中删除通配符,要么禁用此编译的确定性。

请看这个SO答案,它解释了如何删除决定论 (https://stackoverflow.com/a/58101474/1555612)

下面是引用在AssemblyInfo.cs从MSDN:

你可以指定所有的值或你 可以接受默认版本号, 修订号,或两者使用 星号(< em >)。例如, [组装:AssemblyVersion(“2.3.25.1”)] 表示2为主版本,3为 次要版本,25作为构建 编号,1作为修订号。 版本号,例如 [组装:AssemblyVersion(“1.2。< / em >”)) 指定1为主版本,2为 次要版本,并接受 默认版本号和修订号。一个 版本号,例如 [组装:AssemblyVersion(“1.2.15 *”。) 指定1为主版本,2为 次要版本,15作为构建 ,并接受默认值 修订号。默认构建 数字每天递增。默认的 修订号是随机的

这就是说,如果你放一个1.1。*进入组装信息,只有构建号会自动增加,它不会发生在每个构建后,而是每天。修订号会在每次构建时改变,但是是随机的,而不是以递增的方式。

这对于大多数用例来说可能已经足够了。如果这不是你想要的,你不得不写一个脚本,它将自动增加版本#在预构建步骤

你可以使用T4模板机制在Visual Studio中生成所需的简单文本文件源代码:

我想为一些.NET配置版本信息生成 项目。我已经有很长时间没有调查过了 所以我四处寻找,希望能找到一些简单的方法 这一点。我的发现看起来不太令人鼓舞:人们会写作 Visual Studio外接程序和自定义MsBuild任务只是为了获得一个 整数(好吧,可能是两个)。这对一个小女孩来说有点过分了 个人项目。< / p > 灵感来自于StackOverflow的一次讨论 有人建议T4模板可以做这项工作。当然 他们可以。该解决方案只需要最少的工作,不需要Visual Studio 或者构建流程定制。这里应该做什么:

  1. 创建一个扩展名为"的文件。然后将T4模板放在这里,生成AssemblyVersion和AssemblyFileVersion属性:
<#@ template language="C#" #>
//
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
//


using System.Reflection;


[assembly: AssemblyVersion("1.0.1.<#= this.RevisionNumber #>")]
[assembly: AssemblyFileVersion("1.0.1.<#= this.RevisionNumber #>")]
<#+
int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(2010,1,1)).TotalDays;
#>
你必须决定版本号生成算法。为 对我来说,自动生成设置为的修订号就足够了 自2010年1月1日以来的天数。如你所见, 版本生成规则是用纯c#编写的,因此您可以轻松地

    上面的文件应该放在其中一个项目中。我用这个文件创建了一个新项目来进行版本管理 技术清晰。当我构建这个项目时(实际上我甚至不需要 保存文件就足以触发Visual Studio . action),生成如下c#
//
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
//


using System.Reflection;


[assembly: AssemblyVersion("1.0.1.113")]
[assembly: AssemblyFileVersion("1.0.1.113")]
是的,从2010年1月1日到今天已经113天了。明天的

.修订号将改变
    下一步是从所有项目中的AssemblyInfo.cs文件中删除AssemblyVersion和AssemblyFileVersion属性 共享相同的自动生成的版本信息。而是选择“添加” 对于每个项目,导航到T4文件夹 模板文件,选择对应的“。cs”文件作为链接添加。 那就行了!李< / >
我喜欢这种方法的原因是它是轻量级的(没有定制 MsBuild任务),并且不会添加自动生成的版本信息 源代码控制。当然还有使用c#来生成版本

.打开任何复杂度的算法

你可以尝试使用Matt Griffith的UpdateVersion。它现在很旧了,但工作得很好。要使用它,只需要设置一个指向AssemblyInfo.cs文件的预构建事件,应用程序将根据命令行参数相应地更新版本号。

由于应用程序是开源的,我还创建了一个版本,使用(主要版本)。(小版本)。[一][dayofyear])。(增加)格式增加版本号。我已经把我的UpdateVersion应用程序的修改版本的代码放在GitHub: https://github.com/munr/UpdateVersion

你可以使用诸如构建版本控制这样的构建脚本进行更高级的版本控制

如果您在构建和修订visualstudio中添加星号,则使用自2000年1月1日以来的天数作为构建号,并使用自午夜以来的秒数除以2作为修订。

一个更好的救生解决方案是http://autobuildversion.codeplex.com/

它工作起来很有魅力,而且非常灵活。

这是我对T4建议的实现…这将在每次构建项目时增加构建号,而不考虑所选的配置(即调试|发布),并且在每次进行发布构建时增加修订号。您可以通过应用程序& # 10148;装配信息…继续更新主版本号和次版本号

为了更详细地解释,这将读取现有的AssemblyInfo.cs文件,并使用regex找到AssemblyVersion信息,然后根据来自TextTransform.exe的输入增加修订和构建号。

  1. 删除现有的AssemblyInfo.cs文件。
  2. 在它的位置上创建一个AssemblyInfo.tt文件。Visual Studio应该创建AssemblyInfo.cs,并在保存T4文件后将其与T4文件分组。

    <#@ template debug="true" hostspecific="true" language="C#" #>
    <#@ output extension=".cs" #>
    <#@ import namespace="System.IO" #>
    <#@ import namespace="System.Text.RegularExpressions" #>
    <#
    string output = File.ReadAllText(this.Host.ResolvePath("AssemblyInfo.cs"));
    Regex pattern = new Regex("AssemblyVersion\\(\"(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
    MatchCollection matches = pattern.Matches(output);
    if( matches.Count == 1 )
    {
    major = Convert.ToInt32(matches[0].Groups["major"].Value);
    minor = Convert.ToInt32(matches[0].Groups["minor"].Value);
    build = Convert.ToInt32(matches[0].Groups["build"].Value) + 1;
    revision = Convert.ToInt32(matches[0].Groups["revision"].Value);
    if( this.Host.ResolveParameterValue("-","-","BuildConfiguration") == "Release" )
    revision++;
    }
    #>
    
    
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Resources;
    
    
    // General Information
    [assembly: AssemblyTitle("Insert title here")]
    [assembly: AssemblyDescription("Insert description here")]
    [assembly: AssemblyConfiguration("")]
    [assembly: AssemblyCompany("Insert company here")]
    [assembly: AssemblyProduct("Insert product here")]
    [assembly: AssemblyCopyright("Insert copyright here")]
    [assembly: AssemblyTrademark("Insert trademark here")]
    [assembly: AssemblyCulture("")]
    
    
    // Version informationr(
    [assembly: AssemblyVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
    [assembly: AssemblyFileVersion("<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
    [assembly: NeutralResourcesLanguageAttribute( "en-US" )]
    
    
    <#+
    int major = 1;
    int minor = 0;
    int revision = 0;
    int build = 0;
    #>
    
  3. Add this to your pre-build event:

    "%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"
    
  • 版本中的星号(如“2.10.3.*”)-它很简单,但是数字太大了

  • AutoBuildVersion -看起来很棒,但它不适用于我的VS2010。

  • @DrewChapin的脚本工作,但我不能在我的工作室为调试预构建事件和释放预构建事件设置不同的模式。

所以我改变了一点脚本… 命令:< / p >

"%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!$(ConfigurationName)!1 "$(ProjectDir)Properties\AssemblyInfo.tt"

和脚本(这适用于"Debug"和“;Release"配置):

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
int incRevision = 1;
int incBuild = 1;


try { incRevision = Convert.ToInt32(this.Host.ResolveParameterValue("","","Debug"));} catch( Exception ) { incBuild=0; }
try { incBuild = Convert.ToInt32(this.Host.ResolveParameterValue("","","Release")); } catch( Exception ) { incRevision=0; }
try {
string currentDirectory = Path.GetDirectoryName(Host.TemplateFile);
string assemblyInfo = File.ReadAllText(Path.Combine(currentDirectory,"AssemblyInfo.cs"));
Regex pattern = new Regex("AssemblyVersion\\(\"\\d+\\.\\d+\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
MatchCollection matches = pattern.Matches(assemblyInfo);
revision = Convert.ToInt32(matches[0].Groups["revision"].Value) + incRevision;
build = Convert.ToInt32(matches[0].Groups["build"].Value) + incBuild;
}
catch( Exception ) { }
#>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Game engine. Keys: F2 (Debug trace), F4 (Fullscreen), Shift+Arrows (Move view). ")]
[assembly: AssemblyProduct("Game engine")]
[assembly: AssemblyDescription("My engine for game")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyCopyright("Copyright © Name 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]


// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. Only Windows
// assemblies support COM.
[assembly: ComVisible(false)]


// On Windows, the following GUID is for the ID of the typelib if this
// project is exposed to COM. On other platforms, it unique identifies the
// title storage container when deploying this assembly to the device.
[assembly: Guid("00000000-0000-0000-0000-000000000000")]


// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
[assembly: AssemblyVersion("0.1.<#= this.revision #>.<#= this.build #>")]
[assembly: AssemblyFileVersion("0.1.<#= this.revision #>.<#= this.build #>")]


<#+
int revision = 0;
int build = 0;
#>