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

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

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

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

  Version: 0.1.92

如何实现这一目标?

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


当前回答

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

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

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

其他回答

如果您在项目中添加了一个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)

使用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中的所有文件在编译时都应该收到版本信息。

希望这能有所帮助。

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

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

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

你可以在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.

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