September 29, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Applications Licensing using the .NET Framework

  • September 8, 2003
  • By Kenn Scribner
  • Send Email »
  • More Articles »

Alternative Licensing Schemes

I believe Microsoft was obligated to provide a default license provider for the .NET Framework, and they chose to implement one that works very similarly to the licensing for ActiveX controls. But I also believe Microsoft has no intention of using such a simplistic licensing scheme for any of their production software (or at least not for anything significant). Instead, why not provide a licensing scheme that's easier to ship, more clever, harder to break, or whatever? And that's where alternative licensing schemes come in.

You could license your control nearly any way you like. Perhaps you can only design with it on Tuesdays, or you can only execute the control in an application if the weather report for the user's local area is sunny (i.e.: accept the user's postal code and download the weather report from the Internet). I'm actually not joking. You could do these things... That doesn't mean you should, but the licensing process is flexible enough to do so. I'm going to show a more realistic approach, that being a Registry license key. But before I describe this scheme in detail, there is a fact with which you should be aware:

.NET Windows Forms applications are derived from System.Windows.Forms.Form, which is in turn derived from System.Windows.Forms.Control!

Wait a minute... That means, what? Well, what that means is you can license an entire application just as easily as licensing a control. And though the scheme I'll show you targets application licensing versus control licensing, it could apply to both situations. Let's think about the implications of this for a moment.

Application versus Control Licensing

The basic difference between application and control licensing is when you really care about the license. If you develop controls and components for a living, your target market would consist of other software developers. That means your licensing scheme checks for the insertion of a control into a Visual Studio project at design time. Since you probably want to make a few million selling your control library, you'll naturally offer the runtime license for free, or most likely not impose a runtime license at all. After all, you want your target market to sell applications like crazy so they'll buy more controls from you.

Application licensing, however, is different. With applications, we, ourselves, are building the application at design time. It makes no sense to impose any sort of design time license upon ourselves. Rather, we want to make sure the user has the appropriate licensing information in place at run time.

The Framework designers took this into account when they designed the licensing architecture, and you can check for the state of the license request, design time or run time, when the call to GetLicense() is made. I'll actually show both cases, but the only time I'll worry about validating a license is at run time, since I'm showing how applications may be licensed rather than merely licensing controls. It's an important distinction, however, and one you should be aware of.

Registry-Based Licensing

Registry-Based licensing implements a licensing scheme that checks for the presence of a specific Registry key that contains a specific value. The application itself implements no code to write the Registry value--that must be done by the installation application, and since most applications use the Registry anyway, this doesn't pose a significant development limitation. We've been pre-populating Registry keys with our installation applications ever since there was a Registry.

I could, if I wanted, be cleverer regarding the value written to the Registry, but for this example I'll simply write the string "Installed." I'll leave the more clever implementations to you (hey, I can't give away all of my secrets!). The value I'll look for is this:

HKEY_CURRENT_USER\Software\Acme\HostKeys\2de915e1-df71-
3443-9f4d-32259c92ced2

The GUID value you see is a GUID I assigned to my application. Each application Acme Software sells has its own GUID, but through reflection I can use the same license provider for all applications. Ah, the power of .NET at work... I'll stuff all Acme Software license keys here, hence the key name "HostKeys." In your own applications, feel free to shove the key anywhere that is appropriate.

The application is very simple, as you can see from Figure 3.

Figure 3. The Registry-Licensed Application.

If you see this window, the license was valid. On the other hand, if the license was invalid, you'd see the exception dialog you see in Figure 4.

Figure 4. Invalid Registry License Response.

To make this work, we'll need to create a new application and modify the wizard-generated code slightly. By the way, I don't mean ignore the Visual Basic programmers amongst us... The example files contain identical C# and Visual Basic .NET applications. The program code shown here is C#, but the translation is very straightforward.

To begin, we'll need to modify the source code for the main application in four places in addition to writing our own license provider. These four areas are:

  1. The application class declaration (to add some attributes)
  2. The application class constructor
  3. The application class Dispose() method
  4. The application "main" method

I'll also add a using clause since I will employ the GuidAttribute. Let's look first at the class declaration:

/// <summary>
/// Summary description for frmMain.
/// </summary>
[GuidAttribute("2de915e1-df71-3443-9f4d-32259c92ced2")]
[LicenseProvider(typeof(RegistryLicenseProvider))]
public class frmMain : System.Windows.Forms.Form
{
   ...
}

To the class I've added two attributes: GuidAttribute and LicenseProvider. LicenseProvider you've seen, but the purpose of GuidAttribute is to assign a GUID, or a unique numerical value, to this application class. Normally this attribute is used for COM interop, but I'll reuse it here simply to assign the application class a unique numerical identifier that has existing Framework support (that is, we can easily determine the class type's GUID later). I could have generated my own attribute, but then I lose the built-in Framework GUID detection support. It's also important to note that the GUID value I assigned to GuidAttribute matches the GUID value I used as the Registry key. This is the value my license provider will reflect to generate this application's Registry license key value. Because I used GuidAttribute, I had to add this to my collection of namespaces:

using System.Runtime.InteropServices;

To the application class constructor, I add the code you've seen previously:

private License _license = null;

public frmMain()
{
   //
   // Required for Windows Form Designer support
   //
   InitializeComponent();

   // Obtain the license
   _license = LicenseManager.Validate(typeof(frmMain), this);
}

Here I simply call the license manager's Validate() method—nothing special. However, the Validate() method could throw an exception if the license is invalid. Therefore it's a good idea to catch this exception somewhere. But also notice that I added a private data member called _license. Some licensing schemes could make use of this license object (I do not in this example), but in all cases I'll need to dispose of that license when the application terminates. There may be resources assigned to the license that should be released properly. Therefore, I had to modify the application's Dispose() method:

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
   if( disposing )
   {
      if (components != null) 
      {
         components.Dispose();
      }

      if (license != null) 
      {
         license.Dispose();
         license = null;
      }
   }
   base.Dispose( disposing );
}

Here, I just do a quick check for a null license, and if it's not null, I call its Dispose() method and null its reference. Even though in this example I don't use the license, this is required because the license could have resources it must release.

Finally, I modified the applications Main() method to take the license manager's exception into account:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() 
{
   // Create an instance of the licensed application
   frmMain app = null;
   try
   {
      // This will throw a LicenseException if the 
      // license is invalid... if we get an exception,
      // "app" will remain null and the Run() method
      // (below) will not be executed...
      app = new frmMain();
   } // try
   catch (Exception ex)
   {
      // Catch any error, but especially licensing errors...
      string strErr = 
          String.Format("Error executing application: '{0}'",
                        ex.Message);
      MessageBox.Show( strErr,
                       "RegistryLicensedApplication Error",
                       MessageBoxButtons.OK,
                       MessageBoxIcon.Error);
   } // catch

   if ( app != null ) Application.Run(app);
}

The Registry License Provider

As I mentioned previously, the bulk of the license validation is done in your license provider's GetLicense() method. Here is the code for my Registry license provider (found in the examples within the RegistryLicenseProvider.cs source file):

public override License GetLicense(
   LicenseContext context, 
   Type type, 
   object instance, 
   bool allowExceptions) 
{
   // We'll test for the usage mode...run time v. design time.
   // Note we only check if run time...
   if (context.UsageMode == LicenseUsageMode.Runtime) 
   {
      // The Registry key we'll check
      RegistryKey licenseKey = 
    Registry.CurrentUser.OpenSubKey("Software\\Acme\\HostKeys");

      if ( licenseKey != null ) 
      {
         // Passed the first test, which is the existence of the
         // Registry key itself. Now obtain the stored value
         // associated with our app's GUID.
         string strLic =
(string)licenseKey.GetValue(type.GUID.ToString()); // reflected!
         if ( strLic != null ) 
         {
            // Passed the second test, which is some value
            // exists that's associated with our app's GUID.
            if ( String.Compare("Installed",strLic,false) == 0 )
            {
               // Got it...valid license...
               return new RuntimeRegistryLicense(type);
            } // if
         } // if
      } // if

      // if we got this far, we failed the license test. We then
      // check to see if exceptions are allowed, and if so, throw
      // a new license exception...
      if ( allowExceptions == true ) 
      {
         throw new LicenseException(type, 
                                    instance, 
                                    "Your license is invalid");
      } // if

      // Exceptions are not desired, so we'll simply return null.
      return null;
   } // if
   else 
   {
      return new DesigntimeRegistryLicense(type);
   } // else
}

The interesting code begins where we check to see what mode we're currently executing within—design time or run time:

if (context.UsageMode == LicenseUsageMode.Runtime) 
{
   ... // Run time mode
}
else 
{
   ... // Design time mode
} // else

If we're operating at design time, we'll simply create and return an instance of our design time license object:

return new DesigntimeRegistryLicense(type);

However, if run time, we'll open our special Registry key and look for our application's GUID key/value pair. We open the Registry key like so:

RegistryKey licenseKey =
Registry.CurrentUser.OpenSubKey("Software\\Acme\\HostKeys");

And we generate the key by reflecting the application GUID from the object we're given (remember the GuidAttribute we placed on our licensed type?):

string strLic = 
   (string)licenseKey.GetValue(type.GUID.ToString());

The GetValue() method will either return the value associated with the key, or null, so we test for null and then check the returned value against the value we expect to see that represents a valid license:

if ( strLic != null )
{
   // Passed the second test, which is some value
   // exists that's associated with our app's GUID.
   if ( String.Compare("Installed",strLic,false) == 0 )
   {
      // Got it...valid license...
      return new RuntimeRegistryLicense(type);
   } // if
} // if

If everything is fine, we return a new instance of our run time license object. If not, we check to see if exceptions are allowed, and if so, throw a new license exception:

if ( allowExceptions == true ) 
{
   throw new LicenseException(type, 
                              instance, 
                              "Your license is invalid");
} // if

If exceptions aren't allowed, we simply return null.

The license classes in this case are identical, but there is no requirement that they be the same. The run time license is shown here:

public class RuntimeRegistryLicense : License 
{
   private Type type;

   public RuntimeRegistryLicense(Type type) 
   {
      if ( type == null ) 
         throw new NullReferenceException(
"The licensed type reference may not be null.");
      this.type = type;
   }

   public override string LicenseKey 
   {
      get 
      {
         // Simply return the application's GUID
         return type.GUID.ToString();
      }
   }
   public override void Dispose() 
   {
   }
}

Since I derived a new license type from the base License class, I had to override the LicenseKey property (it's an abstract method). In doing so, I return the application GUID when asked. I could, however, re-evaluate the Registry or check for a timed expiration or some other invalidating condition.





Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel