Customer Login Forum Open Source Deutsche Version

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.

When you place a .NET Windows Forms component onto a form, the Visual Studio IDE adds automatically a 'licenses.licx' file to your project. This file is required to license the used components during the runtime of your application. The file does not contain any license keys, but information about the used components.

If WPF is used, or the component is used in a windowless application - for example a Windows Service - you need to add the 'licenses.licx' file manually to the 'Properties' section of your solution.

This will ensure that the component is licensed correctly when distributed with your application to end-users.

licenses.licx file shown in a solution

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.

Design-time mode means that a component is used for software development. Runtime mode means that a component is deployed in an application that is shipped to end-users. The distributed application can use the component, but the component can not be used for software development on end-user machines.

When a 3rd party component is installed for software development by the installer of a component vendor, the installer stores somewhere on the installation machine the information that the component is licensed for software development.

If such a component is placed on a Form in Visual Studio, the IDE asks the component if it has a valid design-time license. Only if a valid design-time license is present, the IDE allows to use the component for software development.

As you build your application, the IDE invokes the License Compiler lc.exe, which in turn scans the licenses.licx file for used components. It then retrieves from each component its runtime-key and embeds it into the application.

If the application is executed, it provides the runtime license key to the component. So the component knows it is licensed, but not for software development, only for deployment.


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.

We created a very small class named 'IdealLicenseManager', which helps to license a component by code. It is available for download at the bottom of this article.

Usage of the IdealLicenseManager class with the Virtual Print Engine .NET component:

VpeControl VpeObject = new VpeControl();
IdealLicenseManager.License(VpeObject);

There is no more coding required. The IdealLicenseManager class tries to obtain the design-time license from the given component. If it can be retrieved, a key file with the name of the component + ".key" is written to disk.

IMPORTANT: 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 automatically read by the IdealLicenseManager class from the key file and then supplied as runtime-license to the component, which completes the licensing mechanism.

The IdealLicenseManager class is designed generically, so it can be used with Virtual Print Engine as well as other components from other vendors that require licensing. But there is one caveat: It is undefined what design time key is returned by a component, if it has no valid design-time key. In regular components should throw an exception, if they are queried for their design time key and there is no valid key present. The IdealLicenseManager class handles such exceptions, but VPE does not throw an exception, because it assumes it is then in trial-version mode. Depending on the component you are using, the if-statement in line 110 - which checks the design-time key - must be changed or enhanced.

//
//  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);
        }
    }
}

bullet Customer's Responses

"Virtual Print Engine was simple to implement yet provided the Printer Control and Power that we could not find in any other Software Program available on the market."

Dan Climent, President, SoftPoint Systems Inc., Fremont, California, USA

More...