dotnet Exception Handling

.NET Exceptions – System.ComponentModel.LicenseException

Winding down our in-depth .NET Exception Handling series, today we’re taking a look at the System.ComponentModel.LicenseException. When creating proprietary applications and .NET components intended to be licensed, you may wish to implement some form of licensing using the built-in LicenseProvider class, which makes it relatively easy to add licensed content to your application. If your application is executed and no valid license is detected a LicenseException is thrown to prompt an indication to the user or developer that licensing must be satisfied.

Throughout this article we’ll explore the LicenseException by looking at where it sits in the massive .NET exception hierarchy. We’ll also look at some functional C# code samples that show a few different techniques for implementing licensing into your own applications, and how failing to do so can (and should) throw LicenseExceptions, so let’s get started!

The Technical Rundown

All .NET exceptions are derived classes of the System.Exception base class, or derived from another inherited class therein. The full exception hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

This code sample also uses the Logging.cs helper class, the full code of which can be found here on GitHub.

When Should You Use It?

Since the LicenseException is thrown when an instantiated Control was unable to locate a valid license that it requires, we’ll start right by looking at how application licensing works in .NET. Unfortunately there isn’t a great deal of easily-accessible official documentation on licensing, but the basics are not too complicated. To start, .NET binds a license to just about any Type of object you want to. This is accomplished by passing an object instance to the LicenseManager.Validate(Type type, object instance) method. However, for most applications a license will be tied to an object that inherits from the System.Windows.Forms.Control class. This ensure that the “main” Form of Control of an application can be checked for a valid license and react accordingly. However, as we’ll see in the sample code, we can license any type of object we wish.

The standard method for licensing is to apply the LicenseProvider attribute for the LicFileLicenseProvider type to the class you wish to license. To illustrate, below we’ve created the custom LicensedComboBox class, which inherits from the built-in ComboBox control class:

The only requirement for implementing a license check in our LicensedComboBox class is to perform the LicenseManager.Validate(Type type, object instance) check somewhere, then be sure to dispose of the license when a class instance is Diposed. As you can see in the first line within our try block, we’re attempting to Validate(...) the current instance (this) using the type that matches this instance (LicensedComboBox).

Let’s try creating a new LicensedComboBox instance and see what happens when our constructor attempts to Validate(...) a license for this object:

Running the code above throws a LicenseException, as seen below:

As it happens, the default way that .NET attempts to locate an actual license is by looking in the base directory of the executable for a license file with the following name format: {AssemblyNamespace}.{ClassName}.lic. Thus, in our case our default license file name is Airbrake.ComponentModel.LicenseException.LicensedComboBox.lic. Since we don’t have any such file, we got the LicenseException seen above.

To remedy this we’ve manually created the Airbrake.ComponentModel.LicenseException.LicensedComboBox.lic file in our Visual Studio project and made sure it copies to the output directory during the build process. However, the mere existence of such a license file is not enough. By default, .NET will look at the content of the .lic file for the following exact keyword string:

So, in our case we’ll add the following string to our .lic file:

Let’s try instantiating a LicensedComboBox again, now that our .lic file is in place:

Running this again now properly validates our license and produces the following output, which includes the generated License instance:

Cool! However, the default method of licensing by sticking a special string in a properly-named .lic file is a bit basic. We could obviously obfuscate the produced key in some way so it cannot be manually created, but let’s take a look at another technique that is commonly used for licensing: modifying the Windows registry.

This gets a fair bit more complicated because we now need to implement our own custom License and LicenseProvider classes. The former allows us to modify what the valid LicenseKey value is and how it is checked, while the latter allows us to modify how the local license is retrieved. Let’s start with our CustomLicense class that inherits License:

Nothing fancy going on here, but using a custom License implementation allows us to override certain methods, like LicenseKey. In this case we just have it return a constant value of 12345, but we could certainly complicate things by retrieving this value from a third-party source like our licensing web service. We’ve also specified the base RegistryKey path that we’ll be using for this license.

The custom LicenseProvider is called RegistryLicenseProvider for us:

As you can see, all we’re really doing here is overriding the GetLicense(...) method, which attempts to retrieve and return a valid License instance based on the passed parameters. The most important of these parameters is the Type type, which we pass into the constructor call of our CustomLicense class. Otherwise, our basic logic is to check if the target registry key exists and, if so, if the LicenseKey value matches the value in the registry at that key. If so, we return a valid CustomLicense instance, otherwise we throw a LicenseException to indicate that the license could not be validated.

Our RegistryLicensedComboBox control is similar to the LicensedComboBox version, expect we’re using the typeof(RegistryLicenseProvider) within the LicenseProvider(...) attribute call:

Before we test this out, we probably want a programmatic way to add/remove the appropriate registry values for testing, so we don’t have to manually edit the registry each time. To accomplish this we have two helper methods, starting with AddLicenseRegistryEntry(Type type):

This creates a new CustomLicense instance of the passed Type type, then checks if the intended RegistryKey path exists. If it doesn’t exist, that sub-key path is created, then a new value with the passed Type type name and the license.LicenseKey value is added.

We also want to be able to remove this entry, so the DeleteLicenseRegistryEntry(Type type) method handles that:

Alright. With everything setup we can test things out by creating a new RegistryLicensedComboBox instance and seeing what happens. We begin by ensuring our registry entry doesn’t exist, then create a new combo box:

As you might suspect, without the proper registry value in place we catch a LicenseException, which includes our custom message:

Let’s try that again, but we’ll first add the license value to the registry:

This time everything works as intended. As the output confirms, we successfully added the new registry key and value for our RegistryLicensedComboBox entry. We were then able to confirm the LicenseKey's expected value of 12345 against the registry entry that matches, which causes the LicenseManager.Validate(...) method call to return a valid CustomLicense instance, as also seen in the log:

There we have it! That’s a brief rundown of how component licensing works in .NET, but there’s obviously a great deal more that can be added on to make licensing your own applications as robust and tamper-proof as you see fit.

To get the most out of your own applications and to fully manage any and all .NET Exceptions, check out the Airbrake .NET Bug Handler, offering real-time alerts and instantaneous insight into what went wrong with your .NET code, along with built-in support for a variety of popular development integrations including: JIRA, GitHub, Bitbucket, and much more.