<p>There are three assembly version attributes. What are differences? Is it ok if I use <code>AssemblyVersion</code> and ignore the rest?</p>

<hr>

<p>MSDN says:</p>

<ul>
<li><p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assemblyversionattribute" rel="noreferrer">AssemblyVersion</a>:</p>

<blockquote>
  <p>Specifies the version of the assembly being attributed. </p>
</blockquote></li>
<li><p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assemblyfileversionattribute" rel="noreferrer">AssemblyFileVersion</a>:</p>

<blockquote>
  <p>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. </p>
</blockquote></li>
<li><p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assemblyinformationalversionattribute" rel="noreferrer">AssemblyInformationalVersion</a>:</p>

<blockquote>
  <p>Defines additional version information for an assembly manifest. </p>
</blockquote></li>
</ul>

<hr>

<p><em>This is a follow-up to <a href="https://stackoverflow.com/questions/62353/what-are-the-best-practices-for-using-assembly-attributes">What are the best practices for using Assembly Attributes?</a></em></p>

[{'answer_id': 64634, 'author': 'Bob King', 'author_id': 6897, 'author_profile': 'https://Stackoverflow.com/users/6897', 'pm_score': 5, 'selected': False, 'text': '<p><code>AssemblyVersion</code> pretty much stays internal to .NET, while <code>AssemblyFileVersion</code> is what Windows sees. If you go to the properties of an assembly sitting in a directory and switch to the version tab, the <code>AssemblyFileVersion</code> is what you\'ll see up top. If you sort files by version, this is what\'s used by Explorer.</p>\n\n<p>The <code>AssemblyInformationalVersion</code> maps to the "Product Version" and is meant to be purely "human-used".</p>\n\n<p><code>AssemblyVersion</code> is certainly the most important, but I wouldn\'t skip <code>AssemblyFileVersion</code>, either. If you don\'t provide <code>AssemblyInformationalVersion</code>, the compiler adds it for you by stripping off the "revision" piece of your version number and leaving the major.minor.build.</p>\n'}, {'answer_id': 64642, 'author': 'Scott Dorman', 'author_id': 1559, 'author_profile': 'https://Stackoverflow.com/users/1559', 'pm_score': 5, 'selected': False, 'text': '<p><code>AssemblyInformationalVersion</code> and <code>AssemblyFileVersion</code> are displayed when you view the "Version" information on a file through Windows Explorer by viewing the file properties. These attributes actually get compiled in to a <code>VERSION_INFO</code> resource that is created by the compiler.</p>\n\n<p><code>AssemblyInformationalVersion</code> is the "Product version" value. <code>AssemblyFileVersion</code> is the "File version" value.</p>\n\n<p>The <code>AssemblyVersion</code> is specific to .NET assemblies and is used by the .NET assembly loader to know which version of an assembly to load/bind at runtime.</p>\n\n<p>Out of these, the only one that is absolutely required by .NET is the <code>AssemblyVersion</code> attribute. Unfortunately it can also cause the most problems when it changes indiscriminately, especially if you are strong naming your assemblies.</p>\n'}, {'answer_id': 65062, 'author': 'Remy van Duijkeren', 'author_id': 8820, 'author_profile': 'https://Stackoverflow.com/users/8820', 'pm_score': 11, 'selected': True, 'text': '<p><strong>AssemblyVersion</strong></p>\n<p>Where other assemblies that reference your assembly will look. If this number changes, other assemblies must update their references to your assembly! Only update this version if it breaks backward compatibility. The <code>AssemblyVersion</code> is required.</p>\n<p>I use the format: <em>major.minor</em> (and <em>major</em> for very stable codebases). This would result in:</p>\n<pre><code>[assembly: AssemblyVersion(&quot;1.3&quot;)]\n</code></pre>\n<p>If you\'re following <a href="https://semver.org/" rel="noreferrer">SemVer</a> strictly then this means you only update when the <em>major</em> changes, so 1.0, 2.0, 3.0, etc.</p>\n<p><strong>AssemblyFileVersion</strong></p>\n<p>Used for deployment (like setup programs). You can increase this number for every deployment.  Use it to mark assemblies that have the same <code>AssemblyVersion</code> but are generated from different builds and/or code.</p>\n<p>In Windows, it can be viewed in the file properties.</p>\n<p>The AssemblyFileVersion is optional. If not given, the AssemblyVersion is used.</p>\n<p>I use the format: <em>major.minor.patch.build</em>, where I follow <a href="https://semver.org/" rel="noreferrer">SemVer</a> for the first three parts and use the buildnumber of the buildserver for the last part (0 for local build).\nThis would result in:</p>\n<pre><code>[assembly: AssemblyFileVersion(&quot;1.3.2.42&quot;)]\n</code></pre>\n<p>Be aware that <a href="https://learn.microsoft.com/en-us/dotnet/api/system.version" rel="noreferrer">System.Version</a> names these parts as <code>major.minor.build.revision</code>!</p>\n<p><strong>AssemblyInformationalVersion</strong></p>\n<p>The Product version of the assembly. This is the version you would use when talking to customers or for display on your website. This version can be a string, like \'<em>1.0 Release Candidate</em>\'.</p>\n<p>The <code>AssemblyInformationalVersion</code> is optional. If not given, the AssemblyFileVersion is used.</p>\n<p>I use the format: <em>major.minor[.patch] [revision as string]</em>. This would result in:</p>\n<pre><code>[assembly: AssemblyInformationalVersion(&quot;1.3 RC1&quot;)]\n</code></pre>\n'}, {'answer_id': 802038, 'author': 'Daniel Fortunov', 'author_id': 5975, 'author_profile': 'https://Stackoverflow.com/users/5975', 'pm_score': 9, 'selected': False, 'text': '<p>Versioning of assemblies in .NET can be a confusing prospect given that there are currently at least three ways to specify a version for your assembly.</p>\n\n<p>Here are the three main version-related assembly attributes:</p>\n\n<pre><code>// Assembly mscorlib, Version 2.0.0.0\n[assembly: AssemblyFileVersion("2.0.50727.3521")]\n[assembly: AssemblyInformationalVersion("2.0.50727.3521")]\n[assembly: AssemblyVersion("2.0.0.0")]\n</code></pre>\n\n<p>By convention, the four parts of the version are referred to as the <strong>Major Version</strong>, <strong>Minor Version</strong>, <strong>Build</strong>, and <strong>Revision</strong>.</p>\n\n<h1>The <code>AssemblyFileVersion</code> is intended to uniquely identify a build of the <em>individual assembly</em></h1>\n\n<p>Typically you’ll manually set the Major and Minor AssemblyFileVersion to reflect the version of the assembly, then increment the Build and/or Revision every time your build system compiles the assembly. The AssemblyFileVersion should allow you to uniquely identify a build of the assembly, so that you can use it as a starting point for debugging any problems.</p>\n\n<p>On my current project we have the build server encode the changelist number from our source control repository into the Build and Revision parts of the AssemblyFileVersion. This allows us to map directly from an assembly to its source code, for any assembly generated by the build server (without having to use labels or branches in source control, or manually keeping any records of released versions).</p>\n\n<p>This version number is stored in the Win32 version resource and can be seen when viewing the Windows Explorer property pages for the assembly.</p>\n\n<p><strong>The CLR does not care about nor examine the AssemblyFileVersion.</strong></p>\n\n<h1>The <code>AssemblyInformationalVersion</code> is intended to represent the version of your entire product</h1>\n\n<p>The AssemblyInformationalVersion is intended to allow coherent versioning of the entire product, which may consist of many assemblies that are independently versioned, perhaps with differing versioning policies, and potentially developed by disparate teams.</p>\n\n<blockquote>\n  <p>“For example, version 2.0 of a product\n  might contain several assemblies; one\n  of these assemblies is marked as\n  version 1.0 since it’s a new assembly\n  that didn’t ship in version 1.0 of the\n  same product. Typically, you set the\n  major and minor parts of this version\n  number to represent the public version\n  of your product. Then you increment\n  the build and revision parts each time\n  you package a complete product with\n  all its assemblies.”\n             — Jeffrey Richter, [CLR via C# (Second Edition)] p. 57</p>\n</blockquote>\n\n<p><strong>The CLR does not care about nor examine the AssemblyInformationalVersion.</strong></p>\n\n<h1>The <code>AssemblyVersion</code> is the only version the CLR cares about (but it cares about the entire <code>AssemblyVersion</code>)</h1>\n\n<p>The AssemblyVersion is used by the CLR to bind to strongly named assemblies. It is stored in the AssemblyDef manifest metadata table of the built assembly, and in the AssemblyRef table of any assembly that references it.</p>\n\n<p>This is very important, because it means that when you reference a strongly named assembly, you are tightly bound to a specific AssemblyVersion of that assembly. The entire AssemblyVersion must be an exact match for the binding to succeed. For example, if you reference version 1.0.0.0 of a strongly named assembly at build-time, but only version 1.0.0.1 of that assembly is available at runtime, binding will fail! (You will then have to work around this using <a href="https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/how-to-enable-and-disable-automatic-binding-redirection" rel="noreferrer">Assembly Binding Redirection</a>.)</p>\n\n<h1>Confusion over whether the entire <code>AssemblyVersion</code> has to match. (Yes, it does.)</h1>\n\n<p>There is a little confusion around whether the entire AssemblyVersion has to be an exact match in order for an assembly to be loaded. Some people are under the false belief that only the Major and Minor parts of the AssemblyVersion have to match in order for binding to succeed. This is a sensible assumption, however it is ultimately incorrect (as of .NET 3.5), and it’s trivial to verify this for your version of the CLR. Just execute <a href="http://webjam-upload.s3.amazonaws.com/assemblybinding___fcbd12afca1d4bb3bf94bf88d1616d25__100__.rar" rel="noreferrer">this sample code</a>.</p>\n\n<p>On my machine the second assembly load fails, and the last two lines of the fusion log make it perfectly clear why:</p>\n\n<pre><code>.NET Framework Version: 2.0.50727.3521\n---\nAttempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f\nSuccessfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f\n---\nAttempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f\nAssembly binding for  failed:\nSystem.IO.FileLoadException: Could not load file or assembly \'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, \nPublicKeyToken=0b3305902db7183f\' or one of its dependencies. The located assembly\'s manifest definition \ndoes not match the assembly reference. (Exception from HRESULT: 0x80131040)\nFile name: \'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f\'\n\n=== Pre-bind state information ===\nLOG: User = Phoenix\\Dani\nLOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f\n (Fully-specified)\nLOG: Appbase = [...]\nLOG: Initial PrivatePath = NULL\nCalling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.\n===\nLOG: This bind starts in default load context.\nLOG: No application configuration file found.\nLOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\config\\machine.config.\nLOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f\nLOG: Attempting download of new URL [...].\nWRN: Comparing the assembly name resulted in the mismatch: Revision Number\nERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.\n</code></pre>\n\n<p>I think the source of this confusion is probably because Microsoft originally intended to be a little more lenient on this strict matching of the full AssemblyVersion, by matching only on the Major and Minor version parts:</p>\n\n<blockquote>\n  <p>“When loading an assembly, the CLR will automatically find the latest\n  installed servicing version that\n  matches the major/minor version of the\n  assembly being requested.”\n              — Jeffrey Richter, [CLR via C# (Second Edition)] p. 56</p>\n</blockquote>\n\n<p>This was the behaviour in Beta 1 of the 1.0 CLR, however this feature was removed before the 1.0 release, and hasn’t managed to re-surface in .NET 2.0:</p>\n\n<blockquote>\n  <p>“Note: I have just described how you\n  should think of version numbers.\n  Unfortunately, the CLR doesn’t treat\n  version numbers this way. [In .NET\n  2.0], the CLR treats a version number as an opaque value, and if an assembly\n  depends on version 1.2.3.4 of another\n  assembly, the CLR tries to load\n  version 1.2.3.4 only (unless a binding\n  redirection is in place). However,\n  <strong>Microsoft has plans to change the\n  CLR’s loader in a future version so\n  that it loads the latest\n  build/revision for a given major/minor\n  version of an assembly</strong>. For example,\n  on a future version of the CLR, if the\n  loader is trying to find version\n  1.2.3.4 of an assembly and version 1.2.5.0 exists, the loader with automatically pick up the latest\n  servicing version. This will be a very\n  welcome change to the CLR’s loader — I\n  for one can’t wait.”\n              — Jeffrey Richter, [CLR via C# (Second Edition)] p. 164 (Emphasis\n  mine)</p>\n</blockquote>\n\n<p>As this change still hasn’t been implemented, I think it’s safe to assume that Microsoft had back-tracked on this intent, and it is perhaps too late to change this now. I tried to search around the web to find out what happened with these plans, but I couldn’t find any answers. I still wanted to get to the bottom of it.</p>\n\n<p>So I emailed Jeff Richter and asked him directly — I figured if anyone knew what happened, it would be him.</p>\n\n<p>He replied  within 12 hours, on a Saturday morning no less, and clarified that the .NET 1.0 Beta 1 loader did implement this ‘automatic roll-forward’ mechanism of picking up the latest available Build and Revision of an assembly, but this behaviour was reverted before .NET 1.0 shipped. It was later intended to revive this but it didn’t make it in before the CLR 2.0 shipped. Then came Silverlight, which took priority for the CLR team, so this functionality got delayed further. In the meantime, most of the people who were around in the days of CLR 1.0 Beta 1 have since moved on, so it’s unlikely that this will see the light of day, despite all the hard work that had already been put into it.</p>\n\n<p>The current behaviour, it seems, is here to stay.</p>\n\n<p>It is also worth noting from my discussion with Jeff that AssemblyFileVersion was only added after the removal of the ‘automatic roll-forward’ mechanism — because after 1.0 Beta 1, any change to the AssemblyVersion was a breaking change for your customers, there was then nowhere to safely store your build number. AssemblyFileVersion is that safe haven, since it’s never automatically examined by the CLR. Maybe it’s clearer that way, having two separate version numbers, with separate meanings, rather than trying to make that separation between the Major/Minor (breaking) and the Build/Revision (non-breaking) parts of the AssemblyVersion.</p>\n\n<h1>The bottom line: Think carefully about when you change your <code>AssemblyVersion</code></h1>\n\n<p>The moral is that if you’re shipping assemblies that other developers are going to be referencing, you need to be extremely careful about when you do (and don’t) change the AssemblyVersion of those assemblies. Any changes to the AssemblyVersion will mean that application developers will either have to re-compile against the new version (to update those AssemblyRef entries) or use assembly binding redirects to manually override the binding.</p>\n\n<ul>\n<li><strong>Do not</strong> change the AssemblyVersion for a servicing release which is intended to be backwards compatible.</li>\n<li><strong>Do</strong> change the AssemblyVersion for a release that you know has breaking changes.</li>\n</ul>\n\n<p>Just take another look at the version attributes on mscorlib:</p>\n\n<pre><code>// Assembly mscorlib, Version 2.0.0.0\n[assembly: AssemblyFileVersion("2.0.50727.3521")]\n[assembly: AssemblyInformationalVersion("2.0.50727.3521")]\n[assembly: AssemblyVersion("2.0.0.0")]\n</code></pre>\n\n<p>Note that it’s the AssemblyFileVersion that contains all the interesting servicing information (it’s the Revision part of this version that tells you what  Service Pack you’re on), meanwhile the AssemblyVersion is fixed at a boring old 2.0.0.0. Any change to the AssemblyVersion would force every .NET application referencing mscorlib.dll to re-compile against the new version!</p>\n'}, {'answer_id': 9323308, 'author': 'linquize', 'author_id': 1031218, 'author_profile': 'https://Stackoverflow.com/users/1031218', 'pm_score': 2, 'selected': False, 'text': "<p>When a assembly' s AssemblyVersion is changed,\nIf it has strong name, the referencing assemblies need to be recompiled, otherwise the assembly does not load!\nIf it does not have strong name, if not explicitly added to project file, it will not be copied to output directory when build so you may miss depending assemblies, especially after cleaning the output directory. </p>\n"}, {'answer_id': 20254633, 'author': 'DavidM', 'author_id': 1422300, 'author_profile': 'https://Stackoverflow.com/users/1422300', 'pm_score': 3, 'selected': False, 'text': "<p>It's worth noting some other things:</p>\n<ol>\n<li><p>As shown in Windows Explorer Properties dialog for the generated assembly file, there are two places called &quot;File version&quot;.  The one seen in the header of the dialog shows the AssemblyVersion, not the AssemblyFileVersion.</p>\n<p>In the Other version information section, there is another element called &quot;File Version&quot;.  This is where you can see what was entered as the AssemblyFileVersion.</p>\n</li>\n<li><p>AssemblyFileVersion is just plain text.  It doesn't have to conform to the numbering scheme restrictions that AssemblyVersion does (&lt;build&gt; &lt; 65K, e.g.).  It can be 3.2.&lt;release tag text&gt;.&lt;datetime&gt;, if you like.  Your build system will have to fill in the tokens.</p>\n<p>Moreover, it is not subject to the wildcard replacement that AssemblyVersion is.  If you just have a value of &quot;3.0.1.*&quot; in the AssemblyInfo.cs, that is exactly what will show in the Other version information-&gt;File Version element.</p>\n</li>\n<li><p>I don't know the impact upon an installer of using something other than numeric file version numbers, though.</p>\n</li>\n</ol>\n"}, {'answer_id': 37982586, 'author': 'KCD', 'author_id': 516748, 'author_profile': 'https://Stackoverflow.com/users/516748', 'pm_score': 3, 'selected': False, 'text': '<p>To keep this question current it is worth highlighting that <code>AssemblyInformationalVersion</code> is used by NuGet and reflects the <strong>package version</strong> including any pre-release suffix.</p>\n\n<p>For example an AssemblyVersion of 1.0.3.* packaged with the asp.net core dotnet-cli</p>\n\n<pre><code>dotnet pack --version-suffix ci-7 src/MyProject\n</code></pre>\n\n<p>Produces a package with version 1.0.3-ci-7 which you can inspect with reflection using:</p>\n\n<pre><code>CustomAttributeExtensions.GetCustomAttribute&lt;AssemblyInformationalVersionAttribute&gt;(asm);\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/64602', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2361/']