我能自动增加文件版本号码吗?在使用Visual Studio时。

396
我在思考如何通过Visual Studio(2005)自动增加构建(和版本?)文件。如果我查看例如C:\Windows\notepad.exe的属性,则版本选项卡会显示“文件版本:5.1.2600.2180”。我也想在我的dll文件版本中得到这些酷炫的数字,而不是1.0.0.0版本,这实在有些无聊。
我尝试了一些方法,但似乎没有开箱即用的功能,或者我可能只是在错误的位置查找(像往常一样)。
我主要使用Web项目... 我查看了以下两个网址:
  1. http://www.codeproject.com/KB/dotnet/Auto_Increment_Version.aspx
  2. http://www.codeproject.com/KB/dotnet/build_versioning.aspx
我无法相信为做某件标准化的事情需要这么多努力。
编辑:据我所知,在VS2005中无法工作(http://www.codeproject.com/KB/dotnet/AutoIncrementVersion.aspx)

1
通配符似乎只适用于VS 2005中的AssemblyVersion,而不适用于AssemblyFileVersion。 - dotnetcoder
有没有适用于VS2005中的C++项目的解决方案?所有答案似乎都与.Net相关。相关问题。谢谢 - Deanna
1
在 .Net Core 项目中,默认情况下 AssemblyVersion 自动递增不起作用。您需要在 csproj 中添加 <Deterministic>False</Deterministic>。请参见 Auto Versioning in Visual Studio 2017 (.NET Core) - Michael Freidgeim
27个回答

455

在Visual Studio 2008中,以下内容有效。

找到AssemblyInfo.cs文件并找到以下两行:

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

您可以尝试将其更改为:

[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]

但这不会产生你想要的结果,你最终会得到一个产品版本号为1.0.*和文件版本号为1.0.0.0,这不是你想要的!

然而,如果你删除这两行中的第二行,只留下:

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

然后编译器将把文件版本设置为与产品版本相等,你就可以得到你想要的结果:自动递增的产品版本和文件版本保持同步。例如:1.0.3266.92689


2
这个和其他任何东西一样好用,并且可以在VS2005中使用。我本来希望得到像1.0.1.56这样的有理数,但我得到了1.0.3266.30135,不过至少它增加了(尽管是一些随机数:D)。 - Ian G
15
哦,我刚刚读了一下:它会自动填入最后两个数字,其中一个是日期(从某个时间点开始算起的天数),另一个是时间(午夜后半秒)。 - Ian G
23
需要移除 AssemblyFileVersion 属性才能使这个工作起来,你对此的判断很准确! - David Faivre
84
我知道这是一个老问题,但我想为那些找到此答案的人添加一条评论。如果你增加了AssemblyVersion,任何使用你的dll的项目都需要重新编译。然而,如果你保持AssemblyVersion不变,仅增加AssemblyFileVersion,那么你可以替换新的dll而无需重新编译正在使用它的内容。所以问问自己,这只是一个新构建,还是我发布了一个新版本? - onefootswill
32
@DD59,“Build”是自2000年1月1日以来的天数,“Revision”是从午夜开始经过的秒数除以2(不是半秒,而是两秒间隔)。参见此处:https://dev59.com/Q3A75IYBdhLWcg3wRWyc#3387167。 - Cristian Diaconescu
显示剩余10条评论

157
打开 AssemblyInfo.cs 文件并进行更改。
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

你可以通过进入项目 -> 属性 -> 程序集信息 在IDE中完成此操作。

然而,这只允许您自动增加程序集版本,并且如果您尝试在文件版本字段中放置*,它将给您

程序集文件版本:此字段不允许使用通配符(“*”)

的消息框。

因此,只需打开assemblyinfo.cs并手动完成即可。


3
这样可以运行:[assembly: AssemblyVersion("1.0.*")] //[assembly: AssemblyFileVersion("1.0.0.0")]。 - Ian G
4
在发布周期中改变Assembly版本号并不可取,而应该改变AssemblyFileVersion。请参考我的博客文章:http://philippetruche.wordpress.com/2008/08/12/net-assembly-versioning-lifecycle/ 另外,可以查看Suzanne Cook在何时更改版本号方面的优秀文章:http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57148.aspx - Philippe
62
注意使用星号,它将在2179年6月4日成为65536时停止工作。 - Lloyd Powell
5
@Shimmy: 在 .csproj 文件中添加 <Deterministic>False</Deterministic>,以便在 Visual Studio 2017 (.NET Core) 中自动进行版本控制。 - Michael Freidgeim
1
@LloydPowell:MS Excel告诉我“6月6日”,所以在你的日期上,你还有2天时间找到解决方法;-) 别忘了告诉你的孙子孙女这个问题。 - Tobias Knauss
显示剩余8条评论

57

另一种每次生成时更改版本号的选项是使用MSBuild.Community.TasksVersion任务。只需下载其安装程序,安装后,适应以下代码并将其粘贴到.csproj文件中<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />之后:

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="BeforeBuild">
    <Version VersionFile="Properties\version.txt" Major="1" Minor="0" BuildType="Automatic" StartDate="12/31/2009" RevisionType="BuildIncrement">
      <Output TaskParameter="Major" PropertyName="Major" />
      <Output TaskParameter="Minor" PropertyName="Minor" />
      <Output TaskParameter="Build" PropertyName="Build" />
      <Output TaskParameter="Revision" PropertyName="Revision" />
    </Version>
    <AssemblyInfo CodeLanguage="CS"
                  OutputFile="Properties\VersionInfo.cs"
                  AssemblyVersion="$(Major).$(Minor)"
                  AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)" />
</Target>

注意: 根据您所在地区调整StartDate属性。 目前它不使用不变的文化。

对于2010年1月14日的第三个构建,这将创建一个带有以下内容的VersionInfo.cs

[assembly: AssemblyVersion("1.0")]
[assembly: AssemblyFileVersion("1.0.14.2")]

需要将此文件添加到项目中(通过 添加现有项),同时需要从 AssemblyInfo.cs 中移除 AssemblyVersionAssemblyFileVersion 行。

更改版本组件的不同算法在 $(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.chm版本属性 中进行了描述。


2
这是我目前看到的规避“FileVersion结构使用16位整数”的可怕事实的最佳方法。 - Mike Post
1
我在使用 Package Console 安装到 VS2012 时遇到了问题,因此建议使用从 https://github.com/loresoft/msbuildtasks/downloads 下载的夜间版 MSI 安装程序。上述内容可以直接复制粘贴。谢谢! - DaveO
在此帖子被拒绝并编辑后,"您可能还想检查一下这个链接http://www.loresoft.com/projects/msbuildtasks/sample-build-file-using-msbuild-community-tasks/default.aspx,它可以改进之前描述的基本功能。" - radu florescu
1
对于那些使用TFS构建的人来说,这不是一个可行的解决方案。最终,这将在VersionInfo.cs和version.txt文件中添加一个待处理编辑。对我而言,每次构建都有一个待处理编辑并不理想。 - JDennis
@JDennis请点击这里获取有关TFS版本控制的技巧... - Christian

32

我提出了一个类似于Christian的解决方案,但不依赖于Community MSBuild tasks,对于我来说这不是一个选择,因为我不想为所有开发人员安装这些任务。

我正在生成代码并编译为程序集,希望自动递增版本号。然而,我不能使用VS 6.0.* AssemblyVersion技巧,因为它每天自动递增构建号,并且会破坏使用旧构建号的程序集的兼容性。相反,我想要一个硬编码的AssemblyVersion,但是自动递增的AssemblyFileVersion。我通过在AssemblyInfo.cs中指定AssemblyVersion,并像这样在MSBuild中生成VersionInfo.cs来实现这一目标,

  <PropertyGroup>
    <Year>$([System.DateTime]::Now.ToString("yy"))</Year>
    <Month>$([System.DateTime]::Now.ToString("MM"))</Month>
    <Date>$([System.DateTime]::Now.ToString("dd"))</Date>
    <Time>$([System.DateTime]::Now.ToString("HHmm"))</Time>
    <AssemblyFileVersionAttribute>[assembly:System.Reflection.AssemblyFileVersion("$(Year).$(Month).$(Date).$(Time)")]</AssemblyFileVersionAttribute>
  </PropertyGroup>
  <Target Name="BeforeBuild">
    <WriteLinesToFile File="Properties\VersionInfo.cs" Lines="$(AssemblyFileVersionAttribute)" Overwrite="true">
    </WriteLinesToFile>
  </Target>

这将生成一个 VersionInfo.cs 文件,其中包含一个 AssemblyFileVersion 的 Assembly 属性,版本遵循 YY.MM.DD.TTTT 的格式,并带有构建日期。您必须将此文件包含在您的项目中并进行构建。


1
MSBuild支持变量吗?最好将[System.DateTime]::Now放入其中一个变量中,否则,在接近午夜时建立可能会导致竞争条件,从而使用旧的构建编号。 - Edward Brey
你是出于演示目的而定义了这四个属性,而不是将它们合并为单个 DateTime.ToString 吗?还是有特殊原因? - mafu
如果你在VS2017中的BeforeBuild事件没有触发,请查看https://dev59.com/Y1cP5IYBdhLWcg3wu8a1 - Rhys Jones
这个解决方案是所有答案中最合适的。然而,问题在于,如果您第二次构建项目会产生不同的时间戳(或versioninfo.cs文件的内容),则时间戳不会更新。如果我关闭并重新加载项目,则时间戳将得到更新。这是MSBuild的一个错误吗?@Boog - Cary
可以在这些标记中执行任何操作吗?使用 $([System.DateTime]::Today.Year - 2010),我得到了一个错误——无法评估表达式 ""24/08/2020 00:00:00".Year - 2010"。找不到方法 'SystemDateTime.Year -2009'。 - sinsedrix
2
这是一个非常棒的解决方案,适合那些想要遵循calver的人!我给你点赞。有一件事我会简化变量:<Date>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</Date>。非常好用。 - Stelios Adamantidis

20

有一个Visual Studio扩展程序Automatic Versions,它支持Visual Studio(2017、2019和2022)。

截图 在这里输入图片描述

在这里输入图片描述


所以我已经卸载了它,而且我可以说更多的是...它修改了原始的csproj文件。我认为这是一个非常有问题的扩展。 - Maxim
3
请尝试使用最新版本,它应该可以在 VS 2017 上运行。 - Rady
出色的工具。在我的vs2017上运行良好。文档可能需要稍微更清晰些,但只需通过网站安装它,然后通过Nuget安装MSBuild,在一个小项目中应用并进行玩耍和构建。很不错。@Boog的答案对我不起作用,尽管他说了我想实现的正是这个。 - err1
1
是的!我喜欢这个产品!! - Missy
支持VS2022! - obnews

18

仅适用于VS2005/2008,带有VS2010的测试版。 - SteveC
https://autobuildversion.codeplex.com/discussions/393154在该主题的末尾附近,r3mote203提供的DropBox链接适用于2010并可在2012(也许是2013)中使用。 - Grault
2
我正在使用适用于VS2012的自动版本,它运行得非常好。 - redcurry

13

获取版本号,请尝试:

 System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
 System.Reflection.AssemblyName assemblyName = assembly.GetName();
 Version version = assemblyName.Version;

要设置版本号,请创建/编辑AssemblyInfo.cs文件。

 [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyFileVersion("1.0.*")]

另外需要说明的是,第三个数字是自2000年2月1日以来的天数,第四个数字是一天总秒数的一半。因此,如果在午夜编译,则应该为零。


10

在Visual Studio 2019中

对我来说仅仅添加这些还不够

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

在构建时,它会抛出以下错误:

指定的版本字符串不符合要求的格式

解决方案

project.csproj中将Deterministic设置为False后,最终接受了该格式。

<Deterministic>false</Deterministic>

编辑:

由于某些原因,将 Deterministic 设置为 False 会破坏我的配置文件,导致在不同的位置加载和保存。

解决方法:

我设置了一个后置构建事件来增加修订号:

后置构建事件批处理脚本

这个调用了一个名为 autoincrement_version.ps1 的 PowerShell 脚本,并将 AssemblyInfo.cs 的路径作为参数传递。

if $(ConfigurationName) == Release (
PowerShell -ExecutionPolicy RemoteSigned $(ProjectDir)autoincrement_version.ps1 '$(ProjectDir)My Project\AssemblyInfo.cs'
)

PowerShell脚本

该脚本使用正则表达式自动增加修订版本号。

param( [string]$file );
  $regex_revision = '(?<=Version\("(?:\d+\.)+)(\d+)(?="\))'
  $found = (Get-Content $file) | Select-String -Pattern $regex_revision
  $revision = $found.matches[0].value
  $new_revision = [int]$revision + 1
  (Get-Content $file) -replace $regex_revision, $new_revision | Set-Content $file -Encoding UTF8

8
在AssemblyInfo或项目属性中将版本号设置为*,如其他帖子所述,并不适用于所有版本的Visual Studio/.NET。据我所知,它在VS 2005中不起作用(但在VS 2003和VS 2008中有效)。对于VS 2005,您可以使用以下内容:在编译时自动增加Visual Studio 2005版本构建和修订号码。但请注意,自动更改版本号并不适用于强名称程序集。原因是每次重新构建引用程序集时,必须更新对该程序集的所有引用,因为强名称程序集引用始终是对特定程序集版本的引用。微软只有在接口发生变化时才更改.NET Framework程序集的版本号。(注:我仍在搜索我阅读过的MSDN链接。)

我认为对于任何版本的VS,你只能在“生成”或“修订”框中放置星号。我刚刚尝试了一下在VS 2005中使用这种方法,效果很好。我不确定那篇代码项目文章的作者在说什么。 - MusiGenesis
也许它回来了,带着一个服务包,但我记得在使用VS 2005时它曾经不起作用。 - Dirk Vollmar
它不适用于2005,我会寻找服务包并回报。 - Ian G
也许MusiGenesis已经安装了一个插件,使得自动版本控制生效。 - Dirk Vollmar
@divo:不,我害怕添加组件。我只有Visual Studio 2005 Professional SP1。我从来没有遇到过*的问题,但我通常手动递增。听起来像是一个奇怪的bug。 - MusiGenesis
@0xA3 我相信你所提到的MSDN链接是http://support.microsoft.com/kb/556041。 - Xcalibur

6
为了将增量(DateTime)信息插入到“ AssemblyFileVersion”属性中,这样做的优点是不会破坏任何依赖关系。
在Boog的解决方案基础上进行改进(对我来说不起作用,可能是因为使用的是VS2008?),可以通过生成文件的预构建事件组合,添加该文件(包括其版本属性),然后再使用一种方法读取这些值。也就是说:
预构建事件:
echo [assembly:System.Reflection.AssemblyFileVersion("%date:~-4,4%.%date:~-7,2%%date:~-10,2%.%time:~0,2%%time:~3,2%.%time:~-5,2%")] > $(ProjectDir)Properties\VersionInfo.cs

将生成的VersionInfo.cs文件(位于Properties子文件夹中)包含到您的项目中。

获取日期的代码(精确到秒):

var version = assembly.GetName().Version;
var fileVersionString = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion;
Version fileVersion = new Version(fileVersionString);
var buildDateTime = new DateTime(fileVersion.Major, fileVersion.Minor/100, fileVersion.Minor%100, fileVersion.Build/100, fileVersion.Build%100, fileVersion.Revision);

不太舒适...而且,我不知道它是否会创建很多强制重新构建(因为文件总是在变化)。

例如,您可以使其更智能,如果您每隔几分钟/小时只更新VersionInfo.cs文件(通过使用临时文件,然后在检测到足够大的更改时复制/覆盖真实的VersionInfo.cs)。 我曾经做过这个相当成功。


它完美地运行。然而,这个正则表达式 %date:-4,4%.%date:-7,2%%date:-10,2%.%time:0,2%%time:3,2%.%time:-5,2%" 太过复杂。 - Cary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接