如何有一个自动递增的版本号(Visual Studio)?
我想存储一组整数,在构build时自动递增:
int MajorVersion = 0; int MinorVersion = 1; int Revision = 92;
当我编译时,它会自动增加Revision
。 当我build立安装项目,它会增加MinorVersion
(我可以手动这样做)。 MajorVersion
只能手动递增。
然后,我可以在菜单Help / About中向用户显示版本号,如下所示:
版本:0.1.92
这怎么能实现?
这个问题不仅要求如何有一个自动递增的版本号,而且要求如何在代码中使用它,这是比其他更完整的答案。
如果将AssemblyInfo类添加到项目中,并将AssemblyVersion属性修改为以星号结尾,例如:
[assembly: AssemblyVersion("2.10.*")]
视觉工作室会根据这些规则为你增加最后的数字(感谢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:
还值得注意的是,如果AssemblyVersion
和AssemblyFileVersion
都被指定了,那么在你的.exe文件中就不会看到这个了。
来自@ BrainSlugs83:
只将第四个数字设置为*
可能是不好的,因为版本不会总是增加。 第三个数字是自2000年以来的天数,第四个数字是午夜以来的秒数(除以2)[IT不是随机]。 所以,如果你在一天的某一天晚些时候build立解决scheme,并且在第二天的早些时候build立解决scheme,那么以后的版本将会有一个较早的版本号。 我build议始终使用XY*
而不是XYZ*
因为您的版本号总是会以这种方式增加。
您可以使用Visual Studio中的T4模板机制从简单的文本文件生成所需的源代码 :
我想为某些.NET项目configuration版本信息生成。 自从我调查可用的选项已经很长时间了,所以我search了一下,希望find一些简单的方法来做到这一点。 我发现看起来并不令人鼓舞:人们编写Visual Studio加载项和自定义的MsBuild任务只是为了获得一个整数(好的,也许是两个)。 这对于一个小小的个人项目来说太过分了。
灵感来自StackOverflow讨论之一,有人build议T4模板可以完成这项工作。 当然可以。 该解决scheme需要最小的努力,并没有Visual Studio或构build过程定制。 这里应该做什么:
- 创build一个扩展名为“.tt”的文件,并在那里放置将生成AssemblyVersion和AssemblyFileVersion属性的T4模板:
<#@ 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; #>
您将不得不决定版本号生成algorithm。 对于我来说,自动生成一个版本号就足够了,这个版本号被设置为自2010年1月1日以来的天数。正如您所看到的,版本生成规则是用纯C#编写的,因此您可以根据需要轻松调整。
- 上面的文件应该放在其中一个项目中。 我用这个单一的文件创build了一个新的项目,使得版本pipe理技术更加清晰。 当我构build这个项目(实际上我甚至不需要构build它:保存文件足以触发Visual Studio操作),将生成以下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属性。 而是为每个项目select“添加现有项目”,使用T4模板文件导航到文件夹,select相应的“.cs”文件并将其添加为链接。 那会做!
我喜欢这种方法,它是轻量级的(没有自定义的MsBuild任务),自动生成的版本信息不会添加到源代码pipe理。 当然,使用C#版本生成algorithm打开任何复杂的algorithm。
如果你在构build和修改时join了一个星号,visual studio使用自2000年1月1日以来的天数作为内部版本号,以及自午夜以来的秒数除以2作为修订版本。
更好的救星解决scheme是http://autobuildversion.codeplex.com/
它像一个魅力,它非常灵活。
这是我的T4build议的实施…基本上,如果你按照我下面概述的步骤,你的项目将增加每个build立项目的内部版本号,不pipeselect的configuration(即debugging|释放),它会增加每次你做一个发布版本的修订版本号。
为了更详细地解释,这将读取现有的AssemblyInfo.cs
文件,并使用正则expression式来查找AssemblyVersion
信息,然后根据来自TextTransform.exe
input增加修订版本号和内部版本号。 请注意,生成和/或版本号只会在从TextTransform.exe
处理时增加。 如果保存.tt
文件或右键单击它,然后单击“运行自定义工具”,则会使AssemblyInfo.cs
文件保持不变。 另外请注意,如果AssemblyInfo.cs
不存在,那么它将为build和revision创build一个值为0的值。
用你的AssemblyInfo.cs
文件replace你的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" #> <# bool incRevision = false; bool incBuild = false; try { incRevision = Convert.ToBoolean(this.Host.ResolveParameterValue("","","revision")); } catch( Exception ) { } try { incBuild = Convert.ToBoolean(this.Host.ResolveParameterValue("","","build")); } catch( Exception ) { } 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?1:0); build = Convert.ToInt32(matches[0].Groups["build"].Value) + (incBuild?1:0); } catch( Exception ) { } #> 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("1.0.<#= this.revision #>.<#= this.build #>")] [assembly: AssemblyFileVersion("1.0.<#= this.revision #>.<#= this.build #>")] [assembly: NeutralResourcesLanguageAttribute( "en-US" )] <#+ int revision = 0; int build = 0; #>
将其添加到您的Debug预生成事件中:
"%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!build!true "$(ProjectDir)Properties\AssemblyInfo.tt"
将此添加到您的发布预构build事件中:
"%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!revision!true -a !!build!true "$(ProjectDir)Properties\AssemblyInfo.tt"
如果您正在使用Web应用程序项目,那么将其添加到预生成事件中:
if $(Configuration) == Debug "%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!build!true "$(ProjectDir)Properties\AssemblyInfo.tt" if $(Configuration) == Release "%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!revision!true -a !!build!true "$(ProjectDir)Properties\AssemblyInfo.tt"
请注意,您可能需要调整一些内容,例如AssemblyInfo.tt
文件的path,并且根据您的Visual Studio版本,还可能需要调整到TextTransform.exe
的path。
以下是MSDN上AssemblyInfo.cs的引用 :
您可以指定所有的值,也可以使用星号( )来接受默认版本号,版本号或两者。 例如,[assembly:AssemblyVersion(“2.3.25.1”)]表示2为主版本,3表示次版本,25表示版本号,1表示版本号。 版本号如[assembly:AssemblyVersion(“1.2。 ”)]指定1作为主要版本,2指定次要版本,并接受默认版本号和修订版号。 版本号如[assembly:AssemblyVersion(“1.2.15。*”)]指定1为主要版本,2为次要版本,15为内部版本号,并接受默认版本号。 默认的内部版本号每天增加。 默认版本号是随机的
这有效地说,如果你把一个1.1。*join到汇编信息中,只有内部版本号会自动增加,并且不会在每一次构build之后发生,而是每天都会发生。 版本号会改变每一个版本,但是是随机的,而不是递增的。
对于大多数使用情况来说,这可能就够了 如果这不是你正在寻找的东西,你就不得不写一个脚本,它会在预生成步骤中自动增加版本#
使用AssemblyInfo.cs
在App_Code中创build文件:并填写以下内容或使用Google获取其他属性/属性的可能性。
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"
(当然用适当的variablesreplacefolderpath)。
我不相信你需要以任何方式为其他类添加编译器选项; App_Code中的所有应用程序在编译时都会收到版本信息。
希望有所帮助。
-
明星版(如“2.10.3。*”) – 很简单,但数字太大
-
AutoBuildVersion – 看起来不错,但它不工作在我的VS2010。
-
druciferre的脚本工作,但我不能在我的工作室设置debugging预生成事件和发布预生成事件不同的模式。
所以我改变了一下脚本… commamd:
"%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\10.0\TextTransform.exe" -a !!$(ConfigurationName)!1 "$(ProjectDir)Properties\AssemblyInfo.tt"
和脚本(这适用于“Debug”和“Release”configuration):
<#@ 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; #>
你可以尝试使用Matt Griffith的UpdateVersion 。 现在已经很老了,但效果很好。 要使用它,只需要设置一个预生成事件,该事件指向AssemblyInfo.cs文件,应用程序将根据命令行参数相应地更新版本号。
由于应用程序是开源的,我也创build了一个版本来使用格式(主要版本)(次要版本)。([year] [dayofyear])。(increment)来增加版本号。 关于这个的更多信息和修改后的代码可以在我的博客文章Assembly Version Numbers和.NET上find 。
更新:我已经把我修改版本的UpdateVersion应用程序的代码放在GitHub上: https : //github.com/munr/UpdateVersion
您可以使用Build Versioning等构build脚本进行更高级的版本控制