AssemblyVersion,AssemblyFileVersion和AssemblyInformationalVersion之间有什么区别?
有三个程序集版本属性。 有什么区别? 如果我使用AssemblyVersion
并忽略其余部分,可以吗?
MSDN说:
-
AssemblyVersion :
指定要归因的组件的版本。
-
AssemblyFileVersion :
指示编译器为Win32文件版本资源使用特定的版本号。 Win32文件版本不需要与程序集的版本号相同。
-
AssemblyInformationalVersion :
为程序集清单定义附加的版本信息。
这是后续什么是使用汇编属性的最佳做法?
的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
程序集的产品版本。 这是您与客户交谈或在网站上显示时使用的版本。 这个版本可以是一个string,比如' 1.0 Release Candidate '。 不幸的是,当你使用一个string,它会产生一个错误的警告 – 已经报告给微软 (在VS2010中修复)。 此外,代码分析将抱怨(CA2243) – 向微软报告 (在VS2013不固定)。 AssemblyInformationalVersion
是可选的。 如果没有给出,则使用AssemblyVersion。
我使用格式: major.minor [修订为string] 。 这将导致:
[assembly: AssemblyInformationalVersion("1.0 RC1")]
这是我最近写的一篇博客文章 ,深入讨论汇编版本的细节。
在.NET中版本化程序集可能是一个令人困惑的前景,因为目前至less有三种方法来为程序集指定一个版本。
以下是与版本相关的三个主要组件属性:
// 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
旨在唯一标识单个程序集的构build
通常,您将手动设置Major和Minor AssemblyFileVersion来反映程序集的版本,然后在您的编译系统每次编译程序集时递增编译和/或修订版本。 AssemblyFileVersion应该允许您唯一标识程序集的构build,以便您可以将其用作debugging任何问题的起点。
在我当前的项目中,我们有构build服务器将来自我们的源代码控制库的变更列表编码到AssemblyFileVersion的Build和Revision部分。 这允许我们直接从程序集映射到它的源代码,构build服务器生成的任何程序集(不必在源代码pipe理中使用标签或分支,或者手动保留发布版本的任何logging)。
此版本号存储在Win32版本资源中,可以在查看程序集的Windows资源pipe理器属性页面时看到。
CLR不关心也不检查AssemblyFileVersion。
AssemblyInformationalVersion
旨在表示您的整个产品的版本
AssemblyInformationalVersion旨在允许对整个产品进行一致的版本控制,其中可能包含许多独立版本的程序集,也许有不同的版本控制策略,并可能由不同的团队开发。
“例如,产品2.0版可能包含多个程序集; 其中一个程序集被标记为1.0版本,因为这是一个新的程序集,并未在同一产品的1.0版中发布。 通常,您将此版本号的主要和次要部分设置为代表您的产品的公共版本。 然后,每次使用所有程序集打包完整产品时,就会增加构build和修订部分。“ – Jeffrey Richter, 通过C#编写CLR(第二版) 57
CLR不关心也不检查AssemblyInformationalVersion。
AssemblyVersion
是CLR唯一关心的版本(但它关心整个AssemblyVersion
)
AssemblyVersion被CLR用来绑定到强命名的程序集。 它存储在构build的程序集的AssemblyDef清单元数据表中,以及任何引用它的程序集的AssemblyRef表中。
这是非常重要的,因为这意味着当您引用一个强命名的程序集时,您紧紧地绑定到该程序集的特定AssemblyVersion。 整个AssemblyVersion必须完全匹配才能成功绑定。 例如,如果在构build时引用强命名程序集的版本1.0.0.0,但该程序集的版本1.0.0.1在运行时可用,则绑定将失败! (您将不得不使用程序集绑定redirect来解决此问题。)
混淆整个AssemblyVersion
是否匹配。 (是的,它确实。)
围绕AssemblyVersion是否必须完全匹配才能加载程序集有点困惑。 有人认为,只有大会的主要部分和次要部分必须相互配合才能成功。 这是一个明智的假设,但是它最终是不正确的(从.NET 3.5开始),并且为你的CLR版本validation这一点是微不足道的。 只要执行这个示例代码 。
在我的机器上,第二个程序集加载失败,并且融合日志的最后两行很清楚为什么:
.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, 通过C#的CLR(第二版) 56
这是1.0 CLR的Beta 1版本中的行为,但是这个特性在1.0版本之前就被删除了,而且还没有设法在.NET 2.0中重新performance出来:
“注意:我刚刚描述过你应该怎么考虑版本号。 不幸的是,CLR不会以这种方式处理版本号。 [在.NET 2.0中],CLR将版本号视为不透明的值,如果程序集依赖于另一个程序集的版本1.2.3.4,则CLR将尝试仅加载版本1.2.3.4(除非已实现绑定redirect)。 但是, 微软计划在未来的版本中更改CLR的加载程序,以便加载给定程序集主要/次要版本的最新版本/修订版 。 例如,在未来版本的CLR上,如果加载程序正在试图查找程序集版本1.2.3.4,并且存在版本1.2.5.0,则加载程序会自动提取最新的服务版本。 这对于CLR的加载程序来说是一个非常可喜的变化 – 我不禁等待。“ – Jeffrey Richter, 通过C#编写的CLR(第二版) 164(强调我的)
由于这个变化还没有被执行,我认为可以肯定的是,微软已经追踪了这个意图,现在改变这个也许为时已晚。 我试图在网上search,以了解这些计划发生了什么,但我找不到任何答案。 我仍然想深究。
所以我给Jeff Richter发邮件,直接问他 – 我想如果有人知道发生了什么事,那就是他。
他在12个小时之内答复了周六上午,并澄清说,.NET 1.0 Beta 1加载程序确实实现了“自动前滚”机制来获取程序集的最新版本的构build和修订版本,但是这种行为是在.NET 1.0发布之前恢复。 它后来打算重振这个,但在CLR 2.0出货之前并没有这样做。 然后,Silverlight,优先考虑CLR团队,所以这个function进一步推迟。 与此同时,在CLR 1.0 Beta 1的时代,大部分人都已经开始了,所以尽pipe已经付出了艰辛的努力,但是这不太可能是白天的事情。
目前的行为似乎在这里停留。
还有一点值得注意的是,在与Jeff的讨论中,AssemblyFileVersion只是在删除了“自动前滚”机制之后才被添加 – 因为在1.0 Beta 1之后,对AssemblyVersion所做的任何更改都是对客户的重大改变,无处安心地存储您的内部版本号。 AssemblyFileVersion是安全的避风港,因为它永远不会被CLR自动检查。 也许这种方式更清晰,有两个独立的版本号,分别具有不同的含义,而不是试图在AssemblyVersion的Major / Minor(破坏)和Build / Revision(非破坏)部分之间进行区分。
底线:仔细想想什么时候改变你的AssemblyVersion
道义在于,如果您要发布其他开发人员将参考的程序集,则在您(而不要)更改这些程序集的AssemblyVersion时,需要非常小心。 对AssemblyVersion的任何更改都意味着应用程序开发者将不得不针对新版本进行重新编译(以更新这些AssemblyRef条目)或使用程序集绑定redirect来手动覆盖绑定。
- 不要为了向后兼容的服务版本而改变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
就是您将看到的顶部。 如果按版本对文件进行sorting,则这是Explorer所使用的内容。
AssemblyInformationalVersion
映射到“产品版本”,意思是纯粹“人为使用”。
AssemblyVersion
肯定是最重要的,但我也不会跳过AssemblyFileVersion
。 如果你没有提供AssemblyInformationalVersion
,那么编译器通过剥离版本号的“revision”部分并离开major.minor.build来为你添加它。
通过查看文件属性,通过Windows资源pipe理器查看文件上的“版本”信息时, AssemblyFileVersion
显示AssemblyInformationalVersion
和AssemblyFileVersion
。 这些属性实际上被编译到由编译器创build的VERSION_INFO
资源中。
AssemblyInformationVersion
是“产品版本”值。 AssemblyFileVersion
是“文件版本”值。
AssemblyVersion
特定于.NET程序集,由.NET程序集加载器用于了解在运行时加载/绑定的程序集版本。
除此之外,.NET唯一需要的就是AssemblyVersion
属性。 不幸的是,当它不加select地改变时也会造成最大的问题,特别是如果你强大的命名你的程序集。
值得注意的是其他一些事情:
1)如生成的程序集文件的Windows资源pipe理器属性对话框中所示,有两个地方称为“文件版本”。 在对话框的头部显示一个显示AssemblyVersion,而不是AssemblyFileVersion。
在其他版本信息部分,还有另一个名为“文件版本”的元素。 在这里你可以看到作为AssemblyFileVersioninput的内容。
2)AssemblyFileVersion只是纯文本。 它不必符合AssemblyVersion所做的编号scheme限制(<build> <65K,例如)。 它可以是3.2。<释放标签文本>。<date时间>,如果你喜欢。 您的构build系统将不得不填写令牌。
此外,它不受汇编版本的通配符替代。 如果您在AssemblyInfo.cs中只有“3.0.1。*”的值,那么其他版本信息 – >文件版本元素中将显示该值。
3)我不知道对使用除数字文件版本号以外的其他安装程序的影响。
为了使这个问题保持最新,值得强调的是NuGet使用AssemblyInformationalVersion
,并且反映了包含任何预发布后缀的包版本 。
例如1.0.3。*的AssemblyVersion与asp.net核心dotnet-cli打包在一起
dotnet pack --version-suffix ci-7 src/MyProject
生成版本为1.0.3-ci-7的软件包,您可以使用以下方法进行reflection检查:
CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
当一个程序集的AssemblyVersion被改变了,如果它有很强的名字,引用程序集需要重新编译,否则程序集不会加载! 如果没有强名称,如果没有明确添加到项目文件中,则在生成时不会将其复制到输出目录,因此可能会错过取决于的程序集,特别是在清除输出目录之后。