867

In AssemblyInfo there are two assembly versions:

  1. AssemblyVersion: Specify the version of the assembly being attributed.
  2. AssemblyFileVersion: 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.

I can get the AssemblyVersion with the following line of code:

Version version = Assembly.GetEntryAssembly().GetName().Version;

But how can I get the AssemblyFileVersion?

John Smith
  • 7,243
  • 6
  • 49
  • 61
Enyra
  • 17,542
  • 12
  • 35
  • 44
  • 2
    What do you mean by "assembly file version" as opposed to "assembly version"? Can you give an example? – Xiaofu May 26 '09 at 08:24
  • 11
    @Xiaofu -- "Assembly Version" is what .NET uses internally. "Assembly File Version" is what shows when you right-click on a file and go to "properties" then the "details" tab. They are not the same. – rory.ap Jan 20 '17 at 18:04
  • I've found that the assembly version is what's used when determining the user.config location in AppData. – Kyle Delaney Oct 30 '17 at 17:54
  • Does this answer your question? [Get the .NET assembly's AssemblyInformationalVersion value?](https://stackoverflow.com/questions/7770068/get-the-net-assemblys-assemblyinformationalversion-value) – Heretic Monkey Jan 05 '23 at 02:46

6 Answers6

1003

See my comment above asking for clarification on what you really want. Hopefully this is it:

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fvi.FileVersion;
billinkc
  • 59,250
  • 9
  • 102
  • 159
Xiaofu
  • 15,523
  • 2
  • 32
  • 45
  • 5
    @Xiaofu: Is there any way to get the version numbers from a AssemblyInfo.cs file instead? – Markus May 08 '12 at 12:07
  • 68
    One problem with this code is that, it'll actually return 1.0.*.* if you haven't specified Build and Revision numbers. AssemblyName.GetAssemblyName(assembly.Location).Version.ToString(); will get you the 'compiled' version number - which should be the same as FileVersion, if you're setting both versions the same way. – Doguhan Uluca Oct 02 '12 at 21:24
  • Nice, but I much rather use the FileMajorPart / FileMinorPart / FileBuildPart / FilePrivatePart properties to get the integers rather than the preformatted FileVersion string. No one likes to see the "1.9.0.0" kind of thing in the title bar of a program. – Nyerguds Oct 03 '15 at 11:39
  • 20
    @DoguhanUluca They're two different things. That'll give you the assembly version, not the file version. "If you're setting both versions the same way" is a workaround, not a solution. – Nyerguds Oct 03 '15 at 11:41
  • 1
    Does `FileVersionInfo` only have `string` properties and no `Version` properties? – Kyle Delaney Oct 30 '17 at 17:59
  • This is good. I'm using it in a winforms project and it is working. – huseyin tugrul buyukisik Nov 02 '17 at 14:47
  • Why do you use **Assembly.GetExecutingAssembly()**? That returns the current dll, but if I want the main executable I'll call: **Assembly.GetEntryAssembly()** – Yitzchak Jun 20 '18 at 11:25
  • 4
    @Yitzchak: `Assembly.GetEntryAssembly()` returns NULL for example in context of Office Add-ins, and also in many other cases. Also, if you think about addins/plugins - EntryAssembly is the host application, and most often you want the version of YourCode(TM) :) Aside from that, it's worth adding to this answer that `assembly.Location` used in the answer can be null as well (i.e. first random case googled out: https://github.com/Azure/azure-functions-host/issues/1233) and that probably happens even more often than having null entry-assembly. – quetzalcoatl Jul 26 '18 at 22:38
  • Is there a way to **set the file version, instead of just getting it?** – Momoro Feb 17 '20 at 05:37
  • Not working. Just returns the AssemblyVersion. – AH. May 27 '21 at 10:50
  • 1
    wow, unbelievable how hard this is in c#.. in electron i just execute "appVersion: app.getVersion()"... yiiiikes... – jebbie Jul 15 '21 at 19:37
  • Note that `FileVersionInfo.GetVersionInfo()` only works for assemblies that physically exist on disk. Does not work with in-memory generated assemblies. – Reyhn May 24 '23 at 12:40
293

There are three versions: assembly, file, and product (aka Assembly Informational Version). They are used by different features and take on different default values if you don't explicit specify them.

string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); 
string assemblyVersion = Assembly.LoadFile("your assembly file").GetName().Version.ToString(); 
string fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; 
string productVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
ankostis
  • 8,579
  • 3
  • 47
  • 61
Check6
  • 2,947
  • 1
  • 15
  • 2
  • 5
    And for those wanting to specify these in the AssemblyInfo.cs file, for assemblyVersion use (with whatever numbers you want) === `[assembly: AssemblyVersion("2.0.*")]` for fileVersion use === `[assembly: AssemblyFileVersion("2.0.*")]` and for productVersion use === `[assembly: AssemblyInformationalVersion("2.0.*")]` The last one may take string suffix for `SemVer` compatibility:`[assembly: AssemblyInformationalVersion("2.0.0-alpha")]` – Jesse Chisholm Sep 08 '16 at 16:04
  • Addendum: `AssemblyFileVersion` may not use the `*` suffix notation. :( It needs all four numbers. `[assembly: AssemblyFileVersion("2.0.0.1")]` – Jesse Chisholm Sep 08 '16 at 16:11
92

When I want to access the application file version (what is set in Assembly Information -> File version), say to set a label's text to it on form load to display the version, I have just used

versionlabel.Text = "Version " + Application.ProductVersion;

This approach requires a reference to System.Windows.Forms.

thatguy
  • 21,059
  • 6
  • 30
  • 40
syntap
  • 1,061
  • 7
  • 3
  • 66
    Note that this requires a reference to System.Windows.Forms, and so might not be suitable for all applications. – BradleyDotNET Jul 14 '14 at 16:59
  • 4
    Unfortunately, that's a string. Not ideal if you want to format it yourself to a more simple "v1.08" kind of format. Much handier if you actually get the version object to get the sub-components from as integers. – Nyerguds Oct 03 '15 at 11:36
  • 1
    Also, this picks up AssemblyFileVersion from AssemblyInfo, not AssemblyVersion, so watch out – dario_ramos Feb 08 '17 at 17:35
28

UPDATE: As mentioned by Richard Grimes in my cited post, @Iain and @Dmitry Lobanov, my answer is right in theory but wrong in practice.

As I should have remembered from countless books, etc., while one sets these properties using the [assembly: XXXAttribute], they get highjacked by the compiler and placed into the VERSIONINFO resource.

For the above reason, you need to use the approach in @Xiaofu's answer as the attributes are stripped after the signal has been extracted from them.


public static string GetProductVersion()
{
  var attribute = (AssemblyVersionAttribute)Assembly
    .GetExecutingAssembly()
    .GetCustomAttributes( typeof(AssemblyVersionAttribute), true )
    .Single();
   return attribute.InformationalVersion;
}

(From http://bytes.com/groups/net/420417-assemblyversionattribute - as noted there, if you're looking for a different attribute, substitute that into the above)

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • Hey Ruben, 2 notes. First, the question asked for AssemblyFileVersion not AssemblyVersion. Second, Assembly.GetExecutingAssembly().GetCustomAttributes( typeof(AssemblyVersionAttribute), true ) returns an array of length 0. I think this is because AssemblyVersionAttribute is not a custom attribute. – Iain Oct 14 '09 at 15:02
  • Re the first point, thats why I said "if you're lookign for a different attribute, substitute that into the above" (IIRC I didnt try it out). Re the second, that does seem plausible but dont have time to dig in... – Ruben Bartelink Oct 14 '09 at 16:12
  • Yeah, you actually can't get AssemblyVersion attribute via .GetCustomAttribute(), assembly version can be retrieved via `AssemblyName.Version` property only. But with every other attribute it's the right way to do it – Dmitrii Lobanov May 14 '13 at 05:06
  • @DmitryLobanov and Iain Thanks for the prompts. I hope the edit covers it sufficiently to make the answer worth keeping instead of deleting - let me know! – Ruben Bartelink May 14 '13 at 11:42
  • 1
    I used `AssemblyInformationalVersionAttribute` instead of `AssemblyVersionAttribute` on .net core 3.1 – Vas Mil Jan 02 '20 at 13:13
14

Use this:

((AssemblyFileVersionAttribute)Attribute.GetCustomAttribute(
    Assembly.GetExecutingAssembly(), 
    typeof(AssemblyFileVersionAttribute), false)
).Version;

Or this:

new Version(System.Windows.Forms.Application.ProductVersion);
Pieter Geerkens
  • 11,775
  • 2
  • 32
  • 52
  • For me this is the best way, as Assembly.Location is an empty string. Must be at the SAAS side blocking this or something, or Azure Service Fabric where it is running in. – KoalaBear Jan 12 '23 at 09:01
1

Cross-posting my answer from a very similar question, because I was googling for my own answer and ended up here. I think the following approach has some advantages compared to the others shown here. Original answer below.


public static string? GetInformationalVersion() =>
    Assembly
        .GetEntryAssembly()
        ?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
        ?.InformationalVersion;

While my answer is similar to some of the others, I think it has some advantages:

  • It determines the informational version of the entry assembly. That means this code can reside in a library in a bigger project and still get's the version of the "program the user has double clicked" without taking any dependency.
    • If you want to get the version of the assembly that the code resides in (i.e. the library not the main program) you can replace GetEntryAssembly() with GetExecutingAssembly()
  • It doesn't determine the informational version by looking at a file. The I/O operation is unneeded and even impossible in some cases (I'm thinking of some single file packaging methods, AoT variants, software executed from UNC paths, etc).
  • It shares the above two aspects with @xanatos' answer, however I like using the generic extension method GetCustomAttribute<T> better and think this variant is more readable.

See also the Microsoft Docs on GetCustomAttribute<T>(Assembly).

Georg Jung
  • 949
  • 10
  • 27