179

Is it possible to get the version number programmatically from any .NET DLL?

If yes, how?

Cœur
  • 37,241
  • 25
  • 195
  • 267
JL.
  • 78,954
  • 126
  • 311
  • 459
  • 2
    check out this link too for auto incrementing version - http://blog.mbcharbonneau.com/2007/03/13/auto-incrementing-build-numbers-in-visual-studio/ – JL. Nov 18 '09 at 12:50

10 Answers10

213

This works if the dll is .net or Win32. Reflection methods only work if the dll is .net. Also, if you use reflection, you have the overhead of loading the whole dll into memory. The below method does not load the assembly into memory.

// Get the file version.
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(@"C:\MyAssembly.dll");

// Print the file name and version number.
Console.WriteLine("File: " + myFileVersionInfo.FileDescription + '\n' +
                  "Version number: " + myFileVersionInfo.FileVersion);

From: http://msdn.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.fileversion.aspx

original source

bluish
  • 26,356
  • 27
  • 122
  • 180
Ben Anderson
  • 7,003
  • 4
  • 40
  • 40
  • 7
    I like this. Why would you bother loading the dll and then use reflection just to get the version, when all you really want to do is this??? – aggieNick02 Feb 25 '13 at 17:19
  • @ben, could you edit the post? I saw I had lost -1 rep from adding a downvote, that I dont remember doing. it wont let me change it, unless you edit the post. cheers! – Luke Duddridge Aug 21 '14 at 09:35
  • 11
    If you would like to make sure you get the executable/dll actually currently in use: instead of a static filename (`@"C:\MyAssembly.dll"` above), you can use `System.Reflection.Assembly.GetExecutingAssembly().Location` (or if a dll: `Assembly.GetAssembly(typeof(AClassInTheDll)).Location`) – Conrad Sep 30 '14 at 18:10
  • 4
    It's the difference between the AssemblyVersion and AssemblyFileVersion attributes. The AssemblyFileVersion gets stamped in such as way as the Windows API can get the value. The AssemblyVersion is part of the strong name and isn't necessarily the same as the AssemblyFileVersion. – daughey Feb 17 '17 at 09:50
129
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
Version ver = assembly.GetName().Version;

Important: It should be noted that this is not the best answer to the original question. Don't forget to read more on this page.

Kris
  • 40,604
  • 9
  • 72
  • 101
  • 37
    This loads MyAssembly.dll into the running AppDomain... bad idea. – staafl Oct 10 '13 at 13:03
  • 2
    @staafl: I felt that's most likely exactly what the OP wanted. If not, there's also "Assembly.ReflectionOnlyLoadFrom" see http://msdn.microsoft.com/en-us/library/system.reflection.assembly.reflectiononlyloadfrom.aspx – Kris Oct 10 '13 at 13:36
  • I don't believe the OP implied it in any way. Also, ReflectionOnlyLoadFrom is has its own side effects - "The reflection-only context is no different from other contexts. Assemblies that are loaded into the context can be unloaded only by unloading the application domain." – staafl Oct 10 '13 at 13:49
  • 15
    I recommend `Assemblyname.GetAssemblyName` to avoid these issues – staafl Oct 10 '13 at 13:50
  • 1
    @staafl: While I'd probably agree `Assemblyname.GetAssemblyName()` is a better choice _now_ (I didn't know about it four years ago) you're calling this method "a bad idea" why not convince me of that with solid arguments? – Kris Oct 10 '13 at 15:17
  • 8
    loading an assembly into the appdomain is slow, irreversible (you can't unload it without killing the domain), requires permissions and is liable to cause side effects, such as executing `beforefieldinit` type initializers, and is just not required in this case. Are these reasons sound enough? – staafl Oct 10 '13 at 15:34
  • 7
    @staafl: Yes; not just for me, but also for everybody else reading this page in the future. – Kris Oct 11 '13 at 12:36
  • 8
    `FileVersionInfo.GetVersionInfo("foo.dll").FileVersion` does well the job and doesn't load the dll into the application. – Jack Jan 21 '15 at 19:06
58

First of all, there are two possible 'versions' that you might be interested in:

  • Windows filesystem file version, applicable to all executable files

  • Assembly build version, which is embedded in a .NET assembly by the compiler (obviously only applicable to .NET assembly dll and exe files)

In the former case, you should use Ben Anderson's answer; in the latter case, use AssemblyName.GetAssemblyName(@"c:\path\to\file.dll").Version, or Tataro's answer, in case the assembly is referenced by your code.

Note that you can ignore all the answers that use .Load()/.LoadFrom() methods, since these actually load the assembly in the current AppDomain - which is analogous to cutting down a tree to see how old it is.

staafl
  • 3,147
  • 1
  • 28
  • 23
42

Here's a nice way using a bit of reflection to get a version of a DLL containing a particular class:

var ver = System.Reflection.Assembly.GetAssembly(typeof(!Class!)).GetName().Version;

Just replace !Class! with the name of a class which is defined in the DLL you wish to get the version of.

This is my preferred method because if I move the DLLs around for different deploys I don't have to change the filepath.

Totero
  • 2,524
  • 20
  • 34
  • 3
    Note that this only works if the assembly in question is statically referenced by the current one. – staafl Oct 10 '13 at 13:02
  • 3
    This is the best answer since the DLL is not necessarily the entry assembly not even the assembly this is called from – CAD bloke Oct 22 '17 at 23:46
  • 1
    See https://stackoverflow.com/a/909583/492 for getting different types of version info. eg `FileVersionInfo` – CAD bloke Oct 23 '17 at 00:20
25

To get it for the assembly that was started (winform, console app, etc...)

using System.Reflection;
...
Assembly.GetEntryAssembly().GetName().Version
Bastien Léonard
  • 60,478
  • 20
  • 78
  • 95
Agent_9191
  • 7,216
  • 5
  • 33
  • 57
12

Kris, your version works great when needing to load the assembly from the actual DLL file (and if the DLL is there!), however, one will get a much unwanted error if the DLL is EMBEDDED (i.e., not a file but an embedded DLL).

The other thing is, if one uses a versioning scheme with something like "1.2012.0508.0101", when one gets the version string you'll actually get "1.2012.518.101"; note the missing zeros.

So, here's a few extra functions to get the version of a DLL (embedded or from the DLL file):

    public static System.Reflection.Assembly GetAssembly(string pAssemblyName)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if (string.IsNullOrEmpty(pAssemblyName)) { return tMyAssembly; }
        tMyAssembly = GetAssemblyEmbedded(pAssemblyName);
        if (tMyAssembly == null) { GetAssemblyDLL(pAssemblyName); }

        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)


    public static System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if(string.IsNullOrEmpty(pAssemblyDisplayName)) { return tMyAssembly; }
        try //try #a
        {
            tMyAssembly = System.Reflection.Assembly.Load(pAssemblyDisplayName);
        }// try #a
        catch (Exception ex)
        {
            string m = ex.Message;
        }// try #a
        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)


    public static System.Reflection.Assembly GetAssemblyDLL(string pAssemblyNameDLL)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if (string.IsNullOrEmpty(pAssemblyNameDLL)) { return tMyAssembly; }
        try //try #a
        {
            if (!pAssemblyNameDLL.ToLower().EndsWith(".dll")) { pAssemblyNameDLL += ".dll"; }
            tMyAssembly = System.Reflection.Assembly.LoadFrom(pAssemblyNameDLL);
        }// try #a
        catch (Exception ex)
        {
            string m = ex.Message;
        }// try #a
        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyFile(string pAssemblyNameDLL)


    public static string GetVersionStringFromAssembly(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssembly(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)


    public static string GetVersionString(Version pVersion)
    {
        string tVersion = "Unknown";
        if (pVersion == null) { return tVersion; }
        tVersion = GetVersionString(pVersion.ToString());
        return tVersion;
    }//string GetVersionString(Version pVersion)


    public static string GetVersionString(string pVersionString)
    {
        string tVersion = "Unknown";
        string[] aVersion;

        if (string.IsNullOrEmpty(pVersionString)) { return tVersion; }
        aVersion = pVersionString.Split('.');
        if (aVersion.Length > 0) { tVersion = aVersion[0]; }
        if (aVersion.Length > 1) { tVersion += "." + aVersion[1]; }
        if (aVersion.Length > 2) { tVersion += "." + aVersion[2].PadLeft(4, '0'); }
        if (aVersion.Length > 3) { tVersion += "." + aVersion[3].PadLeft(4, '0'); }

        return tVersion;
    }//string GetVersionString(Version pVersion)


    public static string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssemblyEmbedded(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)


    public static string GetVersionStringFromAssemblyDLL(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssemblyDLL(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
MacSpudster
  • 121
  • 1
  • 5
4

Answer by @Ben proved to be useful for me. But I needed to check the product version as it was the main increment happening in my software and followed semantic versioning.

myFileVersionInfo.ProductVersion

This method met my expectations

Update: Instead of explicitly mentioning dll path in program (as needed in production version), we can get product version using Assembly.

Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo =FileVersionInfo.GetVersionInfo(assembly.Location); 
string ProdVersion= fileVersionInfo.ProductVersion;
Prasan Dutt
  • 203
  • 2
  • 9
  • Note: if version contains asterisk for auto-incremented value this method will return the asterisk instead of the actual generated number (ie doesn't work if you put 1.0.* in your assembly info). – Ronen Ness Jul 28 '19 at 10:23
  • Yes! However, I chose Jeniks automation for version upgrade so assembly is always having having perfect combination of dll version. – Prasan Dutt Jul 29 '19 at 14:44
2
var versionAttrib = new AssemblyName(Assembly.GetExecutingAssembly().FullName);
BNL
  • 7,085
  • 4
  • 27
  • 32
Invincible
  • 412
  • 3
  • 19
1

You can use System.Reflection.Assembly.Load*() methods and then grab their AssemblyInfo.

Ariel
  • 5,752
  • 5
  • 49
  • 59
0

While the original question may not have been specific to a web service, here is a complete testWebService you can add to display a web service non-cached response plus the file version. We use file version instead of assembly version because we want to know a version, but with all assembly versions 1.0.0.0, the web site can be easily patched (signing and demand link still active!). Replace @Class@ with the name of the web api controller this service is embedded in. It's good for a go/nogo on a web service plus a quick version check.

  [Route("api/testWebService")]
  [AllowAnonymous]
  [HttpGet]
  public HttpResponseMessage TestWebService()
  {
      HttpResponseMessage responseMessage = Request.CreateResponse(HttpStatusCode.OK);
      string loc = Assembly.GetAssembly(typeof(@Class@)).Location;
      FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(loc);
      responseMessage.Content = new StringContent($"<h2>The XXXXX web service GET test succeeded.</h2>{DateTime.Now}<br/><br/>File Version: {versionInfo.FileVersion}");
      responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
      Request.RegisterForDispose(responseMessage);
      return responseMessage;
  }

I found it also necessary to add the following to web.config under configuration to make it truly anonymous

<location path="api/testwebservice">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>