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

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

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

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

  Version: 0.1.92

如何实现这一目标?

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


使用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,我完全错了!)

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

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)


以下是来自MSDN的AssemblyInfo.cs上的引用:

You can specify all the values or you can accept the default build number, revision number, or both by using an asterisk (). For example, [assembly:AssemblyVersion("2.3.25.1")] indicates 2 as the major version, 3 as the minor version, 25 as the build number, and 1 as the revision number. A version number such as [assembly:AssemblyVersion("1.2.")] specifies 1 as the major version, 2 as the minor version, and accepts the default build and revision numbers. A version number such as [assembly:AssemblyVersion("1.2.15.*")] specifies 1 as the major version, 2 as the minor version, 15 as the build number, and accepts the default revision number. The default build number increments daily. The default revision number is random

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

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


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

I wanted to configure version information generation for some .NET projects. It’s been a long time since I investigated available options, so I searched around hoping to find some simple way of doing this. What I’ve found didn’t look very encouraging: people write Visual Studio add-ins and custom MsBuild tasks just to obtain one integer number (okay, maybe two). This felt overkill for a small personal project. The inspiration came from one of the StackOverflow discussions where somebody suggested that T4 templates could do the job. And of course they can. The solution requires a minimal effort and no Visual Studio or build process customization. Here what should be done: Create a file with extension ".tt" and place there T4 template that will generate AssemblyVersion and AssemblyFileVersion attributes:

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

You will have to decide about version number generation algorithm. For me it was sufficient to auto-generate a revision number that is set to the number of days since January 1st, 2010. As you can see, the version generation rule is written in plain C#, so you can easily adjust it to your needs. The file above should be placed in one of the projects. I created a new project with just this single file to make version management technique clear. When I build this project (actually I don’t even need to build it: saving the file is enough to trigger a Visual Studio action), the following C# is generated:

// 
// 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")]

Yes, today it’s 113 days since January 1st, 2010. Tomorrow the revision number will change. Next step is to remove AssemblyVersion and AssemblyFileVersion attributes from AssemblyInfo.cs files in all projects that should share the same auto-generated version information. Instead choose “Add existing item” for each projects, navigate to the folder with T4 template file, select corresponding “.cs” file and add it as a link. That will do! What I like about this approach is that it is lightweight (no custom MsBuild tasks), and auto-generated version information is not added to source control. And of course using C# for version generation algorithm opens for algorithms of any complexity.


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

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


您可以使用构建脚本(如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"


*在版本(如“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;
#>