关于.net:AssemblyVersion,AssemblyFileVersion和AssemblyInformationalVersion之间有什么区别?

What are differences between AssemblyVersion, AssemblyFileVersion and AssemblyInformationalVersion?

有三个程序集版本属性。区别是什么?如果我用AssemblyVersion忽略其余的就可以了吗?

MSDN表示:

  • 程序集版本:


    Specifies the version of the assembly being attributed.

  • 程序集文件版本:


    Instructs a compiler to use a specific version number for the Win32 file version resource. The Win32 file version is not required to be the same as the assembly's version number.

  • 装配信息版本:


    Defines additional version information for an assembly manifest.

这是使用程序集属性的最佳实践的后续步骤?


汇编版本

引用程序集的其他程序集将查找的位置。如果此数字更改,其他程序集必须更新其对程序集的引用!需要AssemblyVersion

我使用的格式是:少校。这将导致:

1
[assembly: AssemblyVersion("1.0")]

程序集文件版本

用于部署。您可以为每个部署增加这个数字。它由安装程序使用。使用它来标记具有相同AssemblyVersion但由不同版本生成的程序集。

在Windows中,可以在文件属性中查看。

如果可能,让它由msbuild生成。assemblyfileversion是可选的。如果未给出,则使用assemblyversion。

我使用格式:major.minor.revision.build,其中我使用revision作为开发阶段(alpha、beta、rc和rtm)、服务包和热修复程序。这将导致:

1
[assembly: AssemblyFileVersion("1.0.3100.1242")]

程序集信息版本

程序集的产品版本。这是您在与客户交谈或在网站上显示时使用的版本。此版本可以是字符串,如"1.0候选版本"。

代码分析将对此进行投诉(CA2243),并报告给微软(在VS2013中未修复)。

AssemblyInformationalVersion是可选的。如果未给定,则使用assemblyfileversion。

我使用的格式是:major.minor[修订为字符串]。这将导致:

1
[assembly: AssemblyInformationalVersion("1.0 RC1")]


考虑到目前至少有三种方法可以为程序集指定版本,.NET中的程序集版本控制可能是一个令人困惑的前景。好的。

以下是与版本相关的三个主要程序集属性:好的。

1
2
3
4
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

按照惯例,版本的四个部分被称为主要版本、次要版本、构建和修订。好的。AssemblyFileVersion旨在唯一地标识单个组件的构建。

通常,您将手动设置主要和次要assemblyfileversion以反映程序集的版本,然后在每次生成系统编译程序集时增加生成和/或修订。assemblyfileversion应允许您唯一地标识程序集的生成,以便可以将其用作调试任何问题的起点。好的。

在我当前的项目中,构建服务器将源代码管理存储库中的变更列表编号编码到assemblyfileversion的构建和修订部分。这允许我们直接从一个程序集映射到它的源代码,对于由构建服务器生成的任何程序集(不必在源代码管理中使用标签或分支,也不必手动保存发布版本的任何记录)。好的。

此版本号存储在Win32版本资源中,在查看程序集的Windows资源管理器属性页时可以看到。好的。

clr不关心也不检查assemblyfileversion。好的。AssemblyInformationalVersion旨在代表整个产品的版本。

assemblyInformationalVersion旨在允许对整个产品进行一致的版本控制,该版本控制可能由许多独立版本控制的程序集组成,可能具有不同的版本控制策略,并且可能由不同的团队开发。好的。

"For example, version 2.0 of a product
might contain several assemblies; one
of these assemblies is marked as
version 1.0 since it’s a new assembly
that didn’t ship in version 1.0 of the
same product. Typically, you set the
major and minor parts of this version
number to represent the public version
of your product. Then you increment
the build and revision parts each time
you package a complete product with
all its assemblies."
— Jeffrey Richter, [CLR via C# (Second Edition)] p. 57

Ok.

clr不关心也不检查assemblyInformationalVersion。好的。AssemblyVersion是clr关心的唯一版本(但它关心的是整个AssemblyVersion)

clr使用assemblyversion绑定到强名称程序集。它存储在已生成程序集的assemblydef manifest元数据表和引用它的任何程序集的assemblyref表中。好的。

这一点非常重要,因为这意味着当引用强名称程序集时,将与该程序集的特定assemblyversion紧密绑定。要使绑定成功,整个assemblyversion必须完全匹配。例如,如果在生成时引用强名称程序集的1.0.0.0版本,但在运行时只有该程序集的1.0.0.1版本可用,则绑定将失败!(然后,您必须使用程序集绑定重定向来解决此问题。)好的。关于整个AssemblyVersion是否必须匹配的困惑。(是的,确实如此。)

对于整个assemblyversion是否必须完全匹配才能加载程序集,存在一些混淆。有些人错误地认为只有程序集版本的主要和次要部分必须匹配才能成功绑定。这是一个合理的假设,但是它最终是不正确的(从.NET 3.5开始),并且为您的clr版本验证这一点很简单。只需执行这个示例代码。好的。

在我的机器上,第二次装配负载失败,Fusion日志的最后两行清楚地说明了原因:好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for  failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral,
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'

=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
 (Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

我认为造成这种混乱的原因可能是,微软原本打算在完全汇编版本的严格匹配上稍微宽容一点,只在主要和次要版本部分进行匹配:好的。

"When loading an assembly, the CLR will automatically find the latest
installed servicing version that
matches the major/minor version of the
assembly being requested."
— Jeffrey Richter, [CLR via C# (Second Edition)] p. 56

Ok.

这是1.0 clr的beta 1中的行为,但是在1.0版本之前,此功能已被删除,并且尚未在.NET 2.0中重新出现:好的。< Buff行情>

"注意:我刚刚描述了你应该考虑版本号。不幸的是,clr没有治疗版本号。[在.NET中]2.0]时,clr将版本号视为不透明值,如果程序集取决于另一个版本的1.2.3.4程序集,clr尝试加载仅适用于1.2.3.4版(除非绑定重定向已就位)。然而,微软计划改变未来版本中的clr加载程序,所以它加载最新的给定主要/次要版本的生成/修订程序集的版本。例如,在未来版本的clr上,如果加载程序正在尝试查找版本1.2.3.4存在1.2.5.0版的程序集,装载机自动拾取最新的维修版本。这将是一个非常欢迎更改clr的加载程序-i因为一个人等不及了。"-Jeffrey Richter,[clr via c(第二版)]164页(强调矿井)好的。< /块引用>

由于这一变化还没有实施,我认为可以肯定的是,微软已经重新跟踪了这一目标,现在改变这一目标可能为时已晚。我试图在网上搜索这些计划的进展情况,但找不到任何答案。我还是想弄清真相。好的。

所以我给杰夫·里克特发了电子邮件,直接问他——我想如果有人知道发生了什么事,那就是他。好的。

他在12小时内回答说,.NET 1.0 Beta 1加载器确实实现了这个"自动前滚"机制,以获取最新的可用版本和程序集修订版,但这种行为在.NET 1.0发货之前被恢复。后来它打算恢复这个功能,但在clr 2.0发布之前没有成功。然后是Silverlight,它优先于clr团队,所以这个功能进一步延迟了。与此同时,在clr 1.0beta1时代的大多数人已经开始行动了,所以这不太可能看到曙光,尽管已经付出了所有的努力。好的。

目前的行为,似乎是为了留下来。好的。

从我与Jeff的讨论中也值得注意的是,assemblyFileVersion仅在删除了"自动前滚"机制之后才被添加-因为在1.0测试版1之后,对assemblyVersion的任何更改都是对客户的一个重大更改,因此没有地方可以安全地存储您的内部版本号。assemblyfileversion是安全的避风港,因为它从未被clr自动检查过。也许这样更清楚,有两个单独的版本号,有不同的含义,而不是试图在assemblyversion的主要/次要(breaking)和构建/修订(non-breaking)部分之间进行分离。好的。底线:当你改变你的AssemblyVersion时要仔细考虑。

道义上是,如果您要运送其他开发人员将要引用的程序集,那么在更改这些程序集的assemblyversion(并且不更改)时,您需要非常小心。对assembly version的任何更改都意味着应用程序开发人员必须根据新版本重新编译(以更新这些assemblyref条目),或者使用程序集绑定重定向手动重写绑定。好的。

  • 不要更改要向后兼容的维护版本的assemblyversion。
  • 请为已知具有破坏性更改的版本更改assemblyversion。

再看看mscorlib上的版本属性:好的。

1
2
3
4
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

请注意,是assemblyfileversion包含所有有趣的服务信息(此版本的修订部分告诉您您使用的是哪个Service Pack),同时assemblyversion被修复为一个无聊的旧2.0.0.0。对assemblyversion的任何更改都将强制引用mscorlib.dll的每个.NET应用程序根据新版本重新编译!好的。好啊。


AssemblyVersion基本上保持在.NET内部,而AssemblyFileVersion是Windows所看到的。如果您转到目录中的程序集属性并切换到版本选项卡,那么您将看到顶部的AssemblyFileVersion。如果按版本对文件排序,这是资源管理器使用的方法。

AssemblyInformationalVersion映射到"产品版本",纯粹是"人类使用"。

AssemblyVersion当然是最重要的,但我也不会跳过AssemblyFileVersion。如果不提供AssemblyInformationalVersion,编译器会去掉版本号的"修订"部分并保留major.minor.build,为您添加它。


通过查看文件属性,通过Windows资源管理器查看文件的"版本"信息时,将显示AssemblyInformationalVersionAssemblyFileVersion。这些属性实际上被编译到由编译器创建的VERSION_INFO资源中。

AssemblyInformationalVersion是"产品版本"值。AssemblyFileVersion是"文件版本"值。

AssemblyVersion特定于.NET程序集,由.NET程序集加载程序使用,以了解运行时要加载/绑定哪个版本的程序集。

其中,.net唯一绝对需要的是AssemblyVersion属性。不幸的是,当它不加选择地更改时,它也会导致大多数问题,特别是在强命名程序集的情况下。


为了使这个问题保持最新,值得强调的是,nuget使用AssemblyInformationalVersion,并反映包版本,包括任何预发布后缀。

例如,1.0.3.*的assemblyversion与ASP.NET core dotnet cli一起打包

1
dotnet pack --version-suffix ci-7 src/MyProject

生成版本为1.0.3-ci-7的包,您可以使用以下方法进行反射检查:

1
CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

值得注意的是:

1)在生成的程序集文件的Windows资源管理器属性对话框中,有两个地方称为"文件版本"。对话框标题中显示的是assemblyversion,而不是assemblyfileversion。

在其他版本信息部分,还有一个元素叫做"文件版本"。在这里您可以看到作为assemblyfileversion输入的内容。

2)assemblyfileversion只是纯文本。它不必符合assemblyversion所做的编号方案限制(<65k,例如)。如果您愿意,它可以是3.2.。您的构建系统必须填充令牌。

此外,assemblyversion不受通配符替换的约束。如果您在assemblyinfo.cs中的值为"3.0.1.*",这正是在其他版本信息->文件版本元素中显示的内容。

3)不过,我不知道使用数字文件版本号以外的东西对安装程序的影响。


当程序集的assemblyversion更改时,如果它有强名称,则需要重新编译引用程序集,否则将不加载程序集!如果它没有强名称,如果没有显式添加到项目文件中,则在生成时不会将其复制到输出目录,因此可能会丢失依赖程序集,特别是在清理输出目录之后。