Licensing .NET Components
Open Source Project
Microsoft invented a special licensing scheme for 3rd party .NET component vendors.
This licensing mechanism allows to sell components and protect their use.
For our product Virtual Print Engine (VPE) you can simply copy the 'licenses.licx' file from one of our sample projects, which are installed with VPE, to the directory of your application and add it to your solution. How it Works
.NET components can be run in two different modes: a design-time mode and a runtime mode.
Licensing By Code
The best way to license a component is by using a licenses.licx file, as explained above.
But we experimented a bit with the inner workings of the .NET licensing mechanisms and came up with some
interesting code, which we present here.
// // Licenser.cs // =========== // // This module handles the licensing of components, which are not placed on a Form. // If a component is placed on a Form, the licensing is done by Windows Forms. // This code tries to obtain the Design Time License from a component. If it can be retrieved, // a key file with the name of the component + ".key" is written to disk. // This key file needs to be shipped with your application for deployment. // // If the Design Time License can not be retrieved from a component, the calling application is // in runtime-mode and the key is read from the file and afterwards supplied as runtime-license // to the component, which completes the licensing mechanism. // // Example Usage: // VpeControl VpeObject = new VpeControl(); // IdealLicenseManager.License(VpeObject); // // Copyright (C) 2012 IDEAL Software GmbH, Neuss, Germany. All rights reserved. // // http://www.IdealSoftware.com // // // This code may be used and distributed freely in source code and binary form, as long as the // above copyright notice and link to www.IdealSoftware.com is left unchanged. // // USE AT YOUR OWN RISK! NO WARRANTIES! // using System; using System.ComponentModel; using System.IO; namespace Licenser { public class MyDesigntimeLicenseContext : LicenseContext { private System.Collections.Hashtable keys = new System.Collections.Hashtable(); public MyDesigntimeLicenseContext() { } public override string GetSavedLicenseKey(Type type, System.Reflection.Assembly resourceAssembly) { return (string)keys[type]; } public override void SetSavedLicenseKey(Type type, string key) { keys[type] = key; } public override LicenseUsageMode UsageMode { get { // It's a 'Designtime'LicenseContext return LicenseUsageMode.Designtime; } } } public class MyRuntimeLicenseContext : LicenseContext { private System.Collections.Hashtable keys = new System.Collections.Hashtable(); public MyRuntimeLicenseContext() { } public override string GetSavedLicenseKey(Type type, System.Reflection.Assembly resourceAssembly) { return (string)keys[type]; } public override void SetSavedLicenseKey(Type type, string key) { keys[type] = key; } public override LicenseUsageMode UsageMode { get { // It's a 'Runtime'LicenseContext return LicenseUsageMode.Runtime; } } } public class IdealLicenseManager { static IdealLicenseManager() { } public static void License(System.ComponentModel.Component component) { string key = GetLicense(component); // The following if-statement can not handle each and every case, since it is // left to the component designer what string is returned, if the component // is not in design-time mode. if (key != null && key != "" && key != "0000") { // we are in design time mode using (StreamWriter outfile = new StreamWriter(component.GetType().Name + ".key")) { outfile.WriteLine(key); } } else { // we are in runtime mode using (StreamReader sr = new StreamReader(component.GetType().Name + ".key")) { key = sr.ReadLine(); } SetLicense(component, key); } } public static string GetLicense(System.ComponentModel.Component component) { // ------------- The following code must be executed on a machine, which has the // ------------- VPE SDK installed, so a valid design time license is available. // ------------- Call this method once when developing your application. // Get the attributes for the component. AttributeCollection attributes = TypeDescriptor.GetAttributes(component); // Get the license provider by retrieving the LicenseProviderAttribute from // the AttributeCollection LicenseProviderAttribute lpa = (LicenseProviderAttribute)attributes[typeof( LicenseProviderAttribute)]; // Create an instance of the LicenseProvider used by // the System.ComponentModel.Component LicenseProvider LicenseProvider = (LicenseProvider)Activator.CreateInstance( lpa.LicenseProvider); // Retrieve the design time key MyDesigntimeLicenseContext context = new MyDesigntimeLicenseContext(); try { LicenseProvider.GetLicense(context, typeof(System.ComponentModel.Component), component, true); } catch (Exception) { return null; } // The design time key is now stored within context, get it as string string key = context.GetSavedLicenseKey( typeof(System.ComponentModel.Component), null); // To-Do: Call this method and store the key persistently, for example to a file. // Ship the file with the key together with your application. // ... return key; } public static void SetLicense(System.ComponentModel.Component component, string key) { // ------------- The following code must be executed on machines, which // ------------- are using VPE without a valid design time license. // ------------- Call this method every time when deploying your application and // ------------- for each new instance of the System.ComponentModel.Component. // To-Do: First of all, retrieve the persistently stored license key, e.g. from // a file // string key = ... // and call this method with the key. // Get the attributes for the component. AttributeCollection attributes = TypeDescriptor.GetAttributes(component); // Get the license provider by retrieving the LicenseProviderAttribute from // the AttributeCollection LicenseProviderAttribute lpa = (LicenseProviderAttribute)attributes[typeof( LicenseProviderAttribute)]; // Create an instance of the LicenseProvider used by // the System.ComponentModel.Component LicenseProvider LicenseProvider = (LicenseProvider)Activator.CreateInstance( lpa.LicenseProvider); // Use the runtime key MyRuntimeLicenseContext context = new MyRuntimeLicenseContext(); context.SetSavedLicenseKey(typeof(System.ComponentModel.Component), key); // Perform the licensing LicenseProvider.GetLicense(context, typeof(System.ComponentModel.Component), component, true); } } } |
Customer's Responses "I just want to say thank you for the excellent support you have been providing. Your prompt and helpful answers are a welcome change from the other third-party control vendors I have dealt with." Andrew K. Martin, Senior Developer, Automated Business Development, Boston, Massachusetts, USA
|