fun with assembly attributes (warning: this is a highly technical post)

since installing, I noticed that I haven’t really been storing Mysterious Space’s version information correctly. well, or not in a way that Windows really understands. as a result, my reports from CrashReporter.NET keep reporting version “”.

I wanted to fix this.

and that lead down an exciting rabbit hole!

SO: in my code, I used to have a few variables, like this:

public const int VERSION = "0.7.5";
public const int RELEASE_YEAR = 2015;
public const int RELEASE_MONTH = 5;
public const int RELEASE_DAY = 24;

a single place for me to keep all the version-related info, that I always made sure to update when compiling for release.

at first I thought I wanted a way to get that VERSION into whatever field Windows and CrashReporter.NET were looking at, but I quickly realized this was backwards; what I REALLY wanted was for VERSION to be populated from the field that Windows and CrashReporter.NET look at: Windows keeps a bunch of application metadata in the “assembly”, including version number, copyright date… all that stuff you see when you right-click an executable and get its properties, and you can’t set that from a variable!

you can find all that stuff in your project’s AssemblyInfo.cs file, which has lines like this:

[assembly: AssemblyTitle("Mysterious Space")]

and this:

[assembly: AssemblyVersion("")]
[assembly: AssemblyFileVersion("")]

hey, those look like version numbers!

but what’s the difference between the two?

honestly, it’s all still a little confusing to me, but the details mostly seems to matter only when you’re building a library, or something; less so when building a stand-alone application. you can read all about it on StackOverflow.

but I also learned that there’s an AssmeblyInformationVersion, and THIS one is intended for display to users, and is listed in your file properties as “Product version”, which sounded EXACTLY like what I wanted, so: in goes:


(it’s perhaps worth mentioning that CrashReporter.NET looks to the AssemblyVersion, so I made sure to set that, as well. though P.S. it irks me that I can’t #define VERSION "0.7.5" and then use that in both places, like I would be able to in C++. I want all the things in place! oh, god, did I just express a longing for C++? sorry, sorry. that was a mistake! :P)

at this point, I still wasn’t sure how I was going to get at this version string in the code, but something else was on my mind: “can I add my release date here, as well?”

I COULD have left it in as those const variables, but that bugged me, somehow. I want all this stuff in ONE PLACE, so that when I go to edit, say, the version string, I KNOW I’ll see the date, too, and so be sure to update it accordingly.

unfortunately, there isn’t a built-in field for storing a release date. fortunately, you can add ANYTHING YOUR HEART DESIRES through the use of custom assembly attributes.

you can google around for how to implement those, but here’s what I came up with for Mysterious Space:

using System;

namespace MysteriousSpace
    class BuildDateAttribute: Attribute
        public int Year { get; private set; }
        public int Month { get; private set; }
        public int Day { get; private set; }

        public BuildDateAttribute(int year, int month, int day)
            Year = year;
            Month = month;
            Day = day;

which allows me to add, in my AssemblyInfo.cs file:

[assembly:BuildDate(2015, 5, 24)]


but NOW: how do we get at that information from within the game code? for example, I display the game’s version and release date in the lower-left of the title menu.

well, the AssemblyInformationalVersion is easy to get at:

string version = Application.ProductVersion;

(you’ll need to be using System.Windows.Forms; to get the Application object.)

getting at custom attributes is a bit trickier, though, and again, in the interest of keeping all this stuff in one place, I created yet another class:

using System.Reflection;
using System.Windows.Forms;

namespace MysteriousSpace
    public class BuildInfo
        public string Version { get; private set; }
        public int Year { get; private set; }
        public int Month { get; private set; }
        public int Day { get; private set; }

        public BuildInfo()
            Version = Application.ProductVersion;

            BuildDateAttribute[] attributes = (BuildDateAttribute[])Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(BuildDateAttribute), false);

            Year = attributes[0].Year;
            Month = attributes[0].Month;
            Day = attributes[0].Day;


now I can just make a new instance of BuildInfo, and I’m good to go. since I’m using MonoGame, I added a public static variable on my main Game object (which I creatively called TheGame), and initialize it before calling Run(). this way, it’s available anywhere:

string releaseDate = TheGame.Build.Year + "-" + TheGame.Build.Month + "-" + TheGame.Build.Day;

ta-da! at last!

as it always is with code, there are many possible solutions to the same problem. I happened to feel strongly that all this information should be in one place, and that lead to the addition of two new classes to my code! overkill? *shrugs* I think it’s cool, and I learned how to do some new stuff. I’m’a call that a win 😛

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s