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

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

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

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

  Version: 0.1.92

如何实现这一目标?

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


当前回答

您可以使用构建脚本(如build versioning)进行更高级的版本控制

其他回答

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

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

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

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

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

Delete your existing AssemblyInfo.cs file. Create a AssemblyInfo.tt file in its place. Visual Studio should create AssemblyInfo.cs and group it with the T4 file after you save the T4 file. <#@ 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; #> Add this to your pre-build event: "%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"

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

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

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

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

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

为了在代码中引用这个版本,以便可以将它显示给用户,可以使用反射。例如,

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:

同样值得注意的是,如果同时指定了AssemblyVersion和AssemblyFileVersion,则在.exe上不会看到此文件。

从@BrainSlugs83:

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

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

(这个帖子开始于2009年) 指定的版本字符串包含与确定性不兼容的通配符。要么从版本字符串中删除通配符,要么禁用此编译的确定性。 看看这个SO答案,它解释了如何消除决定论(https://stackoverflow.com/a/58101474/1555612)

*在版本(如“2.10.3.*”)-它是简单的,但数字太大 AutoBuildVersion -看起来很棒,但它不工作与我的VS2010。 @DrewChapin的脚本工作,但我不能在我的工作室为调试预构建事件和释放预构建事件设置不同的模式。

所以我修改了一下剧本… 命令:

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

和脚本(这适用于“调试”和“发布”配置):

<#@ 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;
#>