it-swarm.cn

AssemblyVersion,AssemblyFileVersion和AssemblyInformationalVersion之间有什么区别?

有三个程序集版本属性。有什么区别?如果我使用AssemblyVersion并忽略其余部分,这样可以吗?


MSDN说:


这是 后续使用汇编属性的最佳做法是什么?

820
Jakub Šturc

AssemblyVersion

引用装配的其他装配体的外观。如果此数字更改,其他程序集必须更新其对程序集的引用! AssemblyVersion是必需的。

我使用的格式为:major.minor。这将导致:

[Assembly: AssemblyVersion("1.0")]

AssemblyFileVersion

用于部署。您可以为每个部署增加此数量。它由安装程序使用。使用它来标记具有相同AssemblyVersion但是从不同构建生成的程序集。

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

如果可能,让它由MSBuild生成。 AssemblyFileVersion是可选的。如果没有给出,则使用AssemblyVersion。

我使用以下格式:major.minor.revision.build,其中我使用修订版进行开发阶段(Alpha,Beta,RC和RTM),服务包和热修复。这将导致:

[Assembly: AssemblyFileVersion("1.0.3100.1242")]

AssemblyInformationalVersion

装配的产品版本。这是您与客户交谈或在您的网站上显示时使用的版本。此版本可以是字符串,例如'1.0 Release Candidate'。

代码分析会抱怨它(CA2243) - 报告给微软 (未在VS2013中修复)。

AssemblyInformationalVersion是可选的。如果没有给出,则使用AssemblyFileVersion。

我使用的格式为:major.minor [revision as string]。这将导致:

[Assembly: AssemblyInformationalVersion("1.0 RC1")]
866
Rémy van Duijkeren

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

以下是三个与主要版本相关的Assembly属性:

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

按照惯例,版本的四个部分称为Major VersionMinor VersionBuildRevision

AssemblyFileVersion旨在唯一标识单个Assembly的构建

通常,您将手动设置Major和Minor AssemblyFileVersion以反映Assembly的版本,然后在每次构建系统编译Assembly时增加Build和/或Revision。 AssemblyFileVersion应该允许您唯一地标识程序集的构建,以便您可以将其用作调试任何问题的起点。

在我当前的项目中,我们让构建服务器将源代码控制存储库中的变更列表编号编码为AssemblyFileVersion的Build和Revision部分。这允许我们直接从程序集映射到其源代码,用于构建服务器生成的任何程序集(无需在源代码管理中使用标签或分支,或手动保留已发布版本的任何记录)。

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

CLR不关心也不检查AssemblyFileVersion。

AssemblyInformationalVersion旨在表示整个产品的版本

AssemblyInformationalVersion旨在允许整个产品的一致版本控制,其可能包含许多独立版本的程序集,可能具有不同的版本控制策略,并且可能由不同的团队开发。

“例如,产品的2.0版本可能包含多个程序集;其中一个程序集标记为1.0版,因为它是一个新的程序集,它没有在同一产品的1.0版本中发布。通常,您可以设置此版本号的主要部分和次要部分,以表示产品的公共版本。然后,每次打包完整产品及其所有组件时,都会增加构建和修订部分。“ - Jeffrey Richter,[CLR通过C#(第二版)] p。 57

CLR不关心也不检查AssemblyInformationalVersion。

AssemblyVersion是CLR唯一关心的版本(但它关心整个AssemblyVersion

CLR使用AssemblyVersion绑定到强名称程序集。它存储在构建的Assembly的AssemblyDef清单元数据表中,以及引用它的任何Assembly的AssemblyRef表中。

这非常重要,因为这意味着当您引用强名称的Assembly时,您将紧密绑定到该Assembly的特定AssemblyVersion。整个AssemblyVersion必须与绑定成功完全匹配。例如,如果在构建时引用强名称Assembly的1.0.0.0版本,但在运行时只有该程序集的1.0.0.1版本可用,则绑定将失败! (然后你必须使用 Assembly Binding Redirection 来解决这个问题。)

关于整个AssemblyVersion是否必须匹配的混淆。 (是的,它确实。)

关于整个AssemblyVersion是否必须完全匹配才能加载程序集,这有点混乱。有些人错误地认为,只有大会版本的主要部分和次要部分必须匹配才能使约束成功。这是一个明智的假设,但它最终是不正确的(从.NET 3.5开始),并且为您的CLR版本验证这一点很简单。只需执行 此示例代码

在我的机器上,第二个装配加载失败,融合日志的最后两行使得它非常清楚原因:

.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.

我认为这种混淆的根源可能是因为微软原本打算对完整AssemblyVersion的这种严格匹配稍微宽松一点,只匹配Major和Minor版本部分:

“当加载程序集时,CLR将自动找到最新安装的服务版本,该版本与所请求的程序集的主要/次要版本相匹配。” - Jeffrey Richter,[CLR通过C#(第二版)] p。 56

这是1.0 CLR的Beta 1中的行为,但是此功能在1.0版本之前被删除,并且未能在.NET 2.0中重新浮出水面:

“注意:我刚刚描述了你应该如何看待版本号。不幸的是,CLR不会以这种方式处理版本号。 [在.NET 2.0中],CLR将版本号视为不透明值,如果程序集依赖于另一个程序集的版本1.2.3.4,则CLR仅尝试加载版本1.2.3.4(除非绑定重定向已到位) )。但是,Microsoft计划在将来的版本中更改CLR的加载程序,以便它为Assembly的给定主要/次要版本加载最新的构建/修订版本。例如,在CLR的未来版本上,如果加载程序试图找到程序集的版本1.2.3.4并且存在版本1.2.5.0,则加载程序会自动获取最新的服务版本。这对CLR的装载机来说是一个非常受欢迎的改变 - 我不能等待。“ - Jeffrey Richter,[CLR来自C#(第二版)] p。 164(强调我的)

由于这一变化仍未实施,我认为可以安全地假设微软已经对此意图进行了回溯,现在改变这一点可能为时已晚。我试图在网上搜索以了解这些计划发生了什么,但我找不到任何答案。我仍然想深究它。

所以我给Jeff Richter发了电子邮件并直接问他 - 我想如果有人知道发生了什么,那就是他。

他在一个星期六的早上12小时内回复,并澄清说.NET 1.0 Beta 1加载器确实实现了这种“自动前滚”机制,可以获取最新的可用构建版本和修订版本,但这种行为是在.NET 1.0发布之前恢复。它后来打算恢复它,但它没有在CLR 2.0发布之前完成。然后是Silverlight,它优先考虑了CLR团队,所以这个功能进一步延迟了。与此同时,CLR 1.0 Beta 1时代的大多数人都已经离开了,所以尽管已经付出了很多艰苦的努力,但这不太可能见到白昼。

目前的行为似乎仍然存在。

我与Jeff的讨论也值得注意的是,只有在删除'自动前滚'机制后才添加AssemblyFileVersion - 因为在1.0 Beta 1之后,对AssemblyVersion的任何更改都是对客户的重大改变,那时候无处安全存储您的内部版本号。 AssemblyFileVersion是安全的避风港,因为它永远不会被CLR自动检查。也许它更清楚,有两个单独的版本号,具有不同的含义,而不是试图在AssemblyVersion的Major/Minor(破坏)和Build/Revision(非破坏)部分之间进行分离。

底线:仔细考虑何时更改AssemblyVersion

道德观点是,如果您正在运送其他开发人员将要引用的程序集,则需要非常小心何时(并且不)更改这些程序集的AssemblyVersion。对AssemblyVersion的任何更改都意味着应用程序开发人员要么必须针对新版本重新编译(更新那些AssemblyRef条目),要么使用程序集绑定重定向来手动覆盖绑定。

  • 不要更改AssemblyVersion以获得旨在向后兼容的服务版本。
  • Do更改AssemblyVersion以获取您知道有更改的版本。

再看看mscorlib上的版本属性:

// 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,其中包含所有有趣的服务信息(它是此版本的Revision部分,告诉您正在使用的Service Pack),同时AssemblyVersion已修复为无聊的旧版2.0.0.0。对AssemblyVersion的任何更改都会强制引用mscorlib.dll的每个.NET应用程序针对新版本重新编译!

566
Daniel Fortunov

AssemblyVersion几乎保留在.NET内部,而AssemblyFileVersion是Windows看到的。如果您转到位于目录中的程序集的属性并切换到版本选项卡,则AssemblyFileVersion是您将在顶部看到的内容。如果按版本对文件进行排序,这就是资源管理器使用的内容。

AssemblyInformationalVersion映射到“产品版本”,并且纯粹是“人类使用”。

AssemblyVersion当然是最重要的,但我也不会跳过AssemblyFileVersion。如果您不提供AssemblyInformationalVersion,编译器会通过剥离版本号的“revision”部分并离开major.minor.build来为您添加它。

41
Bob King

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

AssemblyInformationalVersion是“产品版本”值。 AssemblyFileVersion是“文件版本”值。

AssemblyVersion特定于.NET程序集,.NET程序集加载程序使用它来知道在运行时加载/绑定哪个版本的程序集。

其中,.NET唯一需要的是AssemblyVersion属性。不幸的是,当它不加选择地改变时,它也会导致大多数问题,特别是如果你强烈命名你的程序集。

21
Scott Dorman

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

例如,使用asp.net core dotnet-cli打包的1.0.3。*的AssemblyVersion

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

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

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
7
KCD

值得注意的是其他一些事情:

1)如生成的程序集文件的Windows资源管理器属性对话框中所示,有两个名为“文件版本”的位置。在对话框的标题中看到的那个显示AssemblyVersion,而不是AssemblyFileVersion。

在“其他版本信息”部分中,还有另一个名为“文件版本”的元素。您可以在此处查看作为AssemblyFileVersion输入的内容。

2)AssemblyFileVersion只是纯文本。它不必符合AssemblyVersion所做的编号方案限制(<build> <65K,例如)。它可以是3.2。<release tag text>。<datetime>,如果你愿意的话。您的构建系统必须填写令牌。

此外,它不受AssemblyVersion的通配符替换。如果您在AssemblyInfo.cs中只有一个值“3.0.1。*”,那么这正是将在其他版本信息 - >文件版本元素中显示的内容。

3)但我不知道安装程序使用除数字文件版本号之外的其他东西的影响。

7
DavidM

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

2
linquize