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

StackOverflow https://stackoverflow.com/questions/64602

  •  09-06-2019
  •  | 
  •  

共有三个程序集版本属性。有哪些差异?如果我用的话可以吗 AssemblyVersion 并忽略其余部分?


MSDN 说:

  • 汇编版本:

    指定所归属的程序集的版本。

  • 程序集文件版本:

    指示编译器对 Win32 文件版本资源使用特定版本号。Win32 文件版本不需要与程序集的版本号相同。

  • 装配信息版:

    定义程序集清单的附加版本信息。


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

有帮助吗?

解决方案

汇编版本

引用您的程序集的其他程序集将在哪里查找。如果此数字发生变化,其他程序集必须更新其对您的程序集的引用!这 AssemblyVersion 是必须的。

我使用的格式: 主要次要. 。这将导致:

[assembly: AssemblyVersion("1.0")]

程序集文件版本

用于部署。您可以为每次部署增加此数量。它由安装程序使用。用它来标记具有相同的组件 AssemblyVersion, ,但是是从不同的版本生成的。

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

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

我使用的格式: 主要.次要.修订.构建, ,我使用开发阶段的修订版(Alpha、Beta、RC 和 RTM)、服务包和修补程序。这将导致:

[assembly: AssemblyFileVersion("1.0.3100.1242")]

装配信息版

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

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

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

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

[assembly: AssemblyInformationalVersion("1.0 RC1")]

其他提示

鉴于目前至少有三种方法可以指定程序集的版本,.NET 中程序集的版本控制可能会令人困惑。

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

// 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 旨在唯一标识的构建 单独组装

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

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

此版本号存储在 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 来绑定到强命名程序集。它存储在已构建程序集的 AssemblyDef 清单元数据表中,以及引用它的任何程序集的 AssemblyRef 表中。

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

困惑是否整个 AssemblyVersion 必须匹配。(是的,它确实。)

对于整个 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 的严格匹配稍微宽松一点,只匹配主要版本和次要版本部分:

“加载组件时,CLR将自动找到与所请求的主要/次要版本相匹配的最新安装的维修版本。” - 杰弗里·里希特(Jeffrey Richter),[CLR通过C#(第二版)] p。56

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

“笔记:我刚刚描述了您应该如何想到版本号。不幸的是,CLR不会以这种方式处理版本号。IN .NET 2.0],CLR将版本编号视为不透明的值,如果一个组件取决于另一个组件的1.2.3.4版本,则CLR尝试仅加载版本1.2.3.4(除非有绑定重定向)。然而, 微软计划在将来的版本中更改CLR的加载程序,以便为给定的主要/次要版本加载汇编的最新构建/修订版. 。例如,在CLR的未来版本上,如果加载程序试图找到“汇编”和1.2.5.0版本的版本1.2.3.4,则具有自动拾取最新服务版本的加载程序。这将是对CLR的装载机的非常可喜的变化 - 我迫不及待地想。” - 杰弗里·里希特(Jeffrey Richter),[CLR通过C#(第二版)] p。164(强调我的)

由于这一变化尚未实施,我认为可以肯定的是,微软已经改变了这一意图,现在改变这一点可能为时已晚。我试图在网络上搜索以了解这些计划发生了什么,但我找不到任何答案。我还是想一探究竟。

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

他在 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 的主要/次要(破坏性)和构建/修订(非破坏性)部分之间进行分离。

底线:当你改变自己的想法时要仔细考虑一下 AssemblyVersion

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

  • 不要 更改用于向后兼容的服务版本的 AssemblyVersion。
  • 更改您知道具有重大更改的版本的 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 包含所有有趣的服务信息(该版本的修订版部分告诉您使用的 Service Pack),同时 AssemblyVersion 固定为无聊的旧版本 2.0.0.0。对 AssemblyVersion 的任何更改都会强制引用 mscorlib.dll 的每个 .NET 应用程序针对新版本重新编译!

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

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

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

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

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

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

其中,.NET 绝对需要的唯一一个是 AssemblyVersion 属性。不幸的是,当它不加区别地更改时,它也可能导致大多数问题,特别是当您对程序集进行强命名时。

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

例如,AssemblyVersion 1.0.3.* 与 asp.net core dotnet-cli 一起打包

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

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

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

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

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

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

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

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

3)不过,我不知道使用数字文件版本号以外的其他内容对安装程序有何影响。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top