How to get the assembly version and file version of your own assembly?


The question is, when your assembly is executing, how do you figure out the assembly version and file version of your own assembly?


Your assembly (while executing) can be returned from System.Reflection.Assembly.GetExecutingAssembly(). So:
Assembly Version: Assembly.GetExecutingAssembly().GetName().Version
File Version: System.Diagnostics.FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location)


Of course, this works. But personally, I think it sucks that you need API to get properties of yourself. So here are two suggestions to not use API for those.


1. define a internal class, with only constant class members. It can include your assembly version number, and file version number, please all the interesting assembly properties. Whenever you need to reference your own assembly properties, you use that class.


The downside is that whenever you change the assembly properties, you have to change two places, one in AssemblyInfo.cs, and one in this internal class. But this works well for small projects.


2. Observe the downside of 1), you can do something better. You can have one file describing all the assembly properties. The file can be plain text, or XML, anything, you define it. Before you build your assembly, you run a script that parses that file, and geneates the AssemblyInfo.cs, your internal class. You still reference the assembly properties of your own assembly from that class. When you need to change your properties, you change that file, everything automatically works.


 

Comments (10)

  1. Cory Smith says:

    You use the word API to describe these. Although I agree that it takes an awful lot of work just to find what freakin’ version you are running, however, these are FCL methods, not Win32 API. You didn’t say Win32, but I usually think if API as being so and Framework/FCL/Namespace as .NET.

    Also, are you aware that if you are developing a WindowsForm application that you can get the textual version of the version number via Application.ProductVersion?

    I’ve done some thinking on this… I really can’t seem to justify creating yet another method in the framework in order to accomplish what is already available. It’s a bit confusing that you have the get an AssemblyName object to get the version, but after reading the documentation, I suppose it makes sense. (VB.NET)

    Dim version As System.Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version

    — or —

    Imports System.Reflection.Assembly

    Dim version As Version = GetExecutingAssembly.GetName.Version

    I don’t see what is so difficult with this. Other than it’s not obvious at first where to get the information; however, adding yet another method to do the same thing would have the exact same problem. Am I missing something?

  2. I am not talking about any API. I am talking about constant.

    You can use the APIs I pointed out to get the version information, or, you can do the following:

    internal class MyAssemblyProperties

    {

    internal const string Version = "1.0.0.0";

    internal const string FileVersion = "1.0.0.0";

    }

    Now you want to know what your assembly version is? It is MyAssemblyProperties.Version, as long as you keep it consistent with your AssemblyInfo.cs.

    Why do I need any API to know MY version?

  3. Stefan Casier says:

    Hi Junfeng,

    instead of defining the version yourself, try the following

    typeof (MyNamespace.MyClass).Assembly

    which gives you all the info dynamically 🙂

    Hope this helps

  4. David Levine says:

    Hi JunFeng,

    I agree that it kind of sucks that you have to do so much typing to retrieve your version number, but…

    Anytime you have the same information defined more then once you run the risk of that data getting out of sync; increasing the number of moving parts in a system makes it more fragile. I don’t like the idea of defining the same value more then once.

    In the class you suggested defining, rather then defining the properties as simple strings with the version number embedded directly in them, you could instead define them as

    internal class MyVersionInfo

    {

    static public System.Version AssemblyVersion

    {

    get

    {

    return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

    }

    }

    // etc. for other fields

    }

    This allows the rest of your code to access it just as easily without the downside of having potentially two different values for the versions. You also never need to touch it to update it as the versions change.

    In a large solution you could also put this class in a common file that is shared amongst multiple projects so that all projects will have this class defined for them without requiring you to retype it for each project. I typically separate out the info in the AssemblyInfo.cs file into those attributes that are unique to a project and those that are common to all projects within the solution – (e.g. strong name). You could embed the class once in a common file and have it show up automatically in all the projects.

    Dave

  5. David,

    Your suggestion is exactly what I try to avoid. Every API call has a cost. Call it once, you may not notice the cost. But if it is called 100 times, the cost adds up. It is those little things making your application not perform as fast as it can.

    Chris,

    I am not against using reflection to find other people’s assembly’s version. I am against using reflection to find the assembly version of YOUR OWN assembly. For your own assembly, your assembly version is available to you at source code level. You can simply make a constant, and use that constant in your assembly, as long as you make the constant consistent with your AssemblyInfo.cs. You can’t have a faster way to get your assembly version than this.

    My second recommendation is not justifiable for a single assembly project. But it is very important technique for a many-assembly project. How many times have you changed version number in a complicated project system? Not many. Why? Because your build system is not agile for version change. Having a single file holding version info, and automatically generating relevant class/.cs files for all the assemblies in your project is an important step to make your build system version agile.

    Sorry I replied late. I was doing a little trip.

  6. David Levine says:

    Welcome back,

    If performance is an issue you can modify the property so that it caches the results using lazy initialization. Or you can read and cache it when the program initializes. The cost of doing that should be negligible.

    A while back I wrote a routine that reads the version info from AssemblyInfo.cs, increments the version number (according to a configurable set of rules), and writes the result back out to the file. This file is shared across all the projects in the solution so that all the assembly versions are syncd.

    I build about 30 different assemblies as part of our build process and all assemblies must have the correct version. This is part of our automated build process – whenever I run the build program it automatically generates a new version number for all the assemblies, and also for the MSI and MSM modules that are built in the solution.

    I like this method (reading/writing AssemblyInfo.cs) better then using an external xml file (the build program originally used one) because it’s using the same file the compiler uses so there’s no chance of things getting out of sync. And there’s only one file anyone has to go to for version information. It’s also extremely versatile and easy to use.

    There’s lots of ways of handling this.

    Let me ask you an unrelated question…The fusion layer has several contexts; Load, LoadFrom, etc. Is there a means of determining which assemblies are in each context?

  7. David,

    Yes, I agree. You can make optimization to make it one time cost. My complain is more of pure aesthics.

    It is good that you are doing that. And you know, you can extend that a little bit, and you have exactly my suggestion.

    I’ll start another post to answer your load context question.