Distributing .NET Licensed components using NuGet

5 minute read

If you are building components that are licensed using the .NET Licensing Model, you might have been looking for a way to take benefit from NuGet as a distribution mechanism.

If you are unfamiliar with the .NET Licensing Model, I recommend this excellent article providing you with a good introduction and sample code.

No matter what licensing model you use, an application that consumes a licensed component needs to use a mysterious licenses.licx file and set it as an embedded resource. In addition, the license key or .lic file for the licensed component being consumed must be present.

This makes packaging a .NET licensed component slightly different from packaging a simple assembly.

Licensing a component

To illustrate this, I have a sample component (a Windows Forms user control) that I licensed using the .NET built-in LicFileLicenseProvider. Actually, I used a custom one which inherits from it, just because I can :) The only thing I did was changing the license key that I expect from the consuming application. The following code block contains the entire user control (yep, that's all there is to it). The code required to license the control is highlighted.

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace LicensedComponent
{
  [LicenseProvider(typeof(MyLicFileLicenseProvider))]
  public class LicensedUserControl : UserControl
  {
    private License _license;
    private Label _lblText;

    public LicensedUserControl()
    {
      InitializeComponent();
      _license = LicenseManager.Validate(typeof(LicensedUserControl), this);
      _lblText.Text = _license.LicenseKey;
    }

    private void InitializeComponent()
    {
      _lblText = new Label();
      SuspendLayout();
      _lblText.Dock = DockStyle.Fill;
      _lblText.TextAlign = ContentAlignment.MiddleCenter;

      Controls.Add(_lblText);
      Size = new Size(400, 250);

      ResumeLayout(false);
    }

    protected override void Dispose(bool disposing)
    {
      if (_license != null)
      {
        _license.Dispose();
        _license = null;
      }
      base.Dispose(disposing);
    }
  }
}

You might be wondering why I keep track of the license object: I simply display the license key in the control's label. Note that you can create your own custom license type by inheriting from License (and extend it with properties, e.g. a boolean IsInDemoMode). To customize the licensing mechanism, you simply create your own LicenseProvider. In this case, the MyLicFileLicenseProvider looks as following:

using System.ComponentModel;

namespace LicensedComponent
{
  public class MyLicFileLicenseProvider : LicFileLicenseProvider
  {
    private const string LicenseKeyFormat = "{0} license key: {1}";

    // this key is what makes you a billionaire
    private const string LicenseKey = "{2EDE0218-0996-41D8-9E32-6066F248A215}";

    protected override string GetKey(System.Type type)
    {
      return string.Format(LicenseKeyFormat, type.FullName, LicenseKey);
    }
  }
}

There's only one thing left for this component to be ready for distribution: the license file. The LicFileLicenseProvider tells the .NET runtime to look for a license file. The license file should have a specific name, which is by convention equal to the following pattern: classFullName.lic. Just put it in the component's project.

In this sample, this results in LicensedComponent.LicensedUserControl.lic

Consuming a licensed component

This is heavily dependent on the licensing mechanism obviously. I'll just explain how you can consume the above component to give you an idea. The end result with regard to the licenses.licx file and the NuGet package are the same, which is the goal of this post. For more advanced licensing strategies or inspiration, refer to this post.

As mentioned in this post's introduction, the consumer needs to have a licenses.licx file (describing the list of components that are licensed). Because I used the simple LicFileLicenseProvider, the consuming application must also have a valid .lic file (for each component, containing it's license key). The latter is not needed if you implemented a different licensing mechanism that doesn't require such file (e.g. checking the registry or calling a web service).

For a Windows Forms licensed user control, Visual Studio will create the licenses.licx file for you the moment you drag-n-drop the component onto another control in the designer. In the screenshot above, I just docked my control on the form.

The licenses.licx file contains the following, clearly indicating that the LicensedComponent.LicensedUserControl with version 1.0.0.0 contains a licensed control with the name LicensedComponent.

LicensedComponent.LicensedUserControl, LicensedComponent, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

However, where is the LicensedComponent.LicensedUserControl.lic file containing the required license key? Well, it must be found next to the assembly containing the licensed component. If this would be a NuGet package (which it already is, if you look at the solution), you'd find the assembly somewhere inside the $(SolutionDir)\Packages folder. More specifically: the $(SolutionDir)\Packages\LicensedComponent.1.0.0.0\lib\net40-client folder in this case. Its contents would look like this:

LicensedComponent.LicensedUserControl license key: {2EDE0218-0996-41D8-9E32-6066F248A215}

Why exactly this text? Check the MyLicFileLicenseProvider code again.

As you can see, there's more to it than just adding a reference to the *LicensedComponent.dll, *so the same is true for creating the NuGet package that will distribute it.

Creating a "licensed" NuGet package

The full nuspec file I used to package this licensed user control can be found below. The nuspec is located next to my .csproj file, while I manually created the licenses.licx file myself in the solution directory (one level up, which explains the relative path in the nuspec).

<?xml version="1.0"?>
<package>
  <metadata>
    <version>$version$</version>
    <authors>$author$</authors>
    <owners />
    <id>$id$</id>
    <title />
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
  </metadata>
  <files>
    <file src="..\licenses.licx"
          target="Content\Properties"/>
    <!--
      Ensure the .lic file is packaged next to its
      companion .dll inside the Lib folder
    -->
    <file src="LicensedComponent.LicensedUserControl.lic"
          target="Lib\net40-Client"/>
  </files>
</package>

If I want to give my package consumer a smooth install experience, I should ensure that the proper license is installed as well. In short, I'll simply ensure the LicensedComponent.LicensedUserControl.lic file is shipped next to its assembly, and copy the licenses.licx file into the target project.

Here's the point where you can finally make that remark about why the hell are these license files not XML files! :)

I'd strongly recommend you to create your own licensing mechanism, using XML, registry, services, etc. because my package will not be able to merge the contents of the licenses.licx file into the target project if this file already exists. You can work around it though using PowerShell if you use this file-based mechanism for your components.

Securing the package?

Ok, so you have a package which is worth something. It contains a licensed fully working version of your component (using this very basic licensing mechanism at least). How do I distribute it? Putting it on NuGet.org is a no-go, as everyone can simply consume it without paying the license fee.

Here's an alternative: create a private NuGet feed on MyGet. Simply give access to those people who paid for it, and secure it for others.

Again, I used a very basic licensing mechanism only to demonstrate how you can embed a file-based license into your NuGet package and pointed out you can secure your feed with granular access instead of worrying about your package. It's up to you to ensure your licensing mechanism doesn't support distributing the licensed package elsewhere! (this proof-of-concept doesn't mitigate this at all, so be warned!)

The code as well as the NuGet package are attached to this blog:

Leave a Comment