PLUSManaged: Custom SystemIdentifierAlgorithm Implementations

The PLUSManaged library is designed so that it is extremely extensible to allow for highly customized implementations. This includes a framework which enables you to implement your own means of uniquely identifying what is authorized to use a given license. The SystemIdentifierAlgorithm and SystemIdentifier abstract classes may be derived to implement your algorithm, and this walk-through explains how to do this in detail. To get the most out of this walk-through, we suggest making a copy of one of the sample applications and following the steps outlined below in that new copy.

Important

It is imperative to keep in mind that you are responsible for testing any custom system identifier algorithms you create to ensure that the reliability and uniqueness of the identifiers meet your expectations and requirements.

Before you begin, you will want to simply determine the name of your algorithm. For the purposes of this walk-through, we will simply call this "CustomExample".

Implementation

Creating the Classes

First, we will create our two new classes required to implement our "CustomExample" algorithm: CustomExampleIdentifierAlgorithm and CustomExampleIdentifier. These new classes will:

  1. Be defined in files which match the class name ("CustomExampleIdentifierAlgorithm.cs" and "CustomExampleIdentifier.cs", respectively)
  2. Extend the SystemIdentifierAlgorithm and SystemIdentifier classes in PLUSManaged, respectively.
  3. Reference the com.softwarekey.Client.Licensing namespace.

Following the instructions above, the ExampleCustomIdentifier class should initially look something like this:

C#
using System;
using System.Collections.Generic;
using com.softwarekey.Client.Licensing;

namespace YourApplicationsNamespace
{
public class ExampleCustomIdentifier : SystemIdentifier
{
}
}
Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports com.softwarekey.Client.Licensing

Namespace YourApplicationsNamespace
Public Class ExampleCustomIdentifier
Inherits SystemIdentifier
End Class
End Namespace

...And the ExampleCustomIdentifierAlgorithm class should initially look something like this:

C#
using System;
using System.Collections.Generic;
using com.softwarekey.Client.Licensing;

namespace YourApplicationsNamespace
{
public class ExampleCustomIdentifierAlgorithm : SystemIdentifierAlgorithm
{
}
}
Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports com.softwarekey.Client.Licensing

Namespace YourApplicationsNamespace
Public Class ExampleCustomIdentifierAlgorithm
Inherits SystemIdentifierAlgorithm
End Class
End Namespace

Implementing the Custom Identifier Class

Now that the identifier class is defined, the next step is to define and implement the required members and constructors...

  1. Add a protected static int member variable, which will be used to automatically increment default ID's for the collection of identifiers.  In this example, we named this m_customExampleIdentifierId and defaulted its value to 1.
  2. Several constructors, which all need to call base class constructors, need to be created...
    1. A default constructor that does not accept any arguments.
    2. A constructor that accepts an identifier's value.
    3. A constructor that accepts an identifier's name and value
    4. A constructor that accepts an identifier's name, value, and a hash.
  3. Next, the constructors need to be implemented...
    1. Constructors 1 and 2 above are meant to be used when generating a new list of identifiers for the current system, so these constructors need to use the static integer to pre-populate the name and increment the static integer. Since the second constructor also receives a value, it must also pre-populate the member variable used for the value property.
    2. The last two constructors are meant for loading authorized identifiers from a license file, so these do not need to pre-populate the name.
  4. Finally, the class also needs to override the Type property so it returns the name of the class.

Following the steps above, the ExampleCustomIdentifier class should now look something like this:

C#
using System;
using System.Collections.Generic;
using com.softwarekey.Client.Licensing;

namespace YourApplicationsNamespace
{
public class ExampleCustomIdentifier : SystemIdentifier
{
protected static int m_exampleCustomIdentifierId = 1;

public ExampleCustomIdentifier()
{
m_name = "ExampleCustomIdentifier" + m_exampleCustomIdentifierId.ToString();
m_exampleCustomIdentifierId++;
}

public ExampleCustomIdentifier(string value)
{
m_name = "ExampleCustomIdentifier" + m_exampleCustomIdentifierId.ToString();
m_exampleCustomIdentifierId++;

m_value = value;
}

public ExampleCustomIdentifier(string name, string value)
: base(name, value)
{
}

public ExampleCustomIdentifier(string name, string value, string hash)
: base(name, value, hash, "ExampleCustomIdentifier")
{
}

public override string Type
{
get { return "ExampleCustomIdentifier"; }
}
}
}
Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports com.softwarekey.Client.Licensing

Namespace YourApplicationsNamespace
Public Class ExampleCustomIdentifier
Inherits SystemIdentifier

Protected Shared m_exampleCustomIdentifierId As Integer = 1

Public Sub New()
m_name = "ExampleCustomIdentifier" & m_exampleCustomIdentifierId.ToString()
m_exampleCustomIdentifierId += 1
End Sub

Public Sub New(ByVal value As String)
m_name = "ExampleCustomIdentifier" & m_exampleCustomIdentifierId.ToString()
m_exampleCustomIdentifierId += 1

m_value = value
End Sub

Public Sub New(ByVal name As String, ByVal value As String)
MyBase.New(name, value)
End Sub

Public Sub New(ByVal name As String, ByVal value As String, ByVal hash As String)
MyBase.New(name, value, hash, "ExampleCustomIdentifier")
End Sub

Public Overrides ReadOnly Property Type As String
Get
Return "ExampleCustomIdentifier"
End Get
End Property
End Class
End Namespace

This concludes the implementation of the ExampleCustomIdentifier class.

Implementing the Custom Algorithm Class

With the algorithm class defined, the first step is to implement a default constructor for the class, which also must call the base class (SystemIdentifierAlgorithm) constructor and pass in the ID of the algorithm (which should really only be the same as the name of the algorithm). So the class file would then look something like this:

C#
using System;
using System.Collections.Generic;
using com.softwarekey.Client.Licensing;

namespace YourApplicationsNamespace
{
public class ExampleCustomIdentifierAlgorithm : SystemIdentifierAlgorithm
{
public ExampleCustomIdentifierAlgorithm() : base("ExampleCustom") { }
}
}
Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports com.softwarekey.Client.Licensing

Namespace YourApplicationsNamespace
Public Class ExampleCustomIdentifierAlgorithm
Inherits SystemIdentifierAlgorithm

Public Sub New()
MyBase.New("ExampleCustom")
End Sub
End Class
End Namespace

Of course, you are free to add your own initialization logic in the default constructor here. Since this example does not require any custom initialization logic, the constructor will remain empty and will do nothing more than simply call the base constructor of SystemIdentifierAlgorithm.

Lastly, we will need to implement an override for the GetIdentifiers() method. This method is used to generate a list of identifiers representing the current system, and is typically where you implement your logic to provide the proper values that are used to identify the authorized system. Since this method returns a generic list, the list returned may return one or more than one identifier, though this example will only use a single identifier. An example of an algorithm that only ever returns a single identifier here is the built-in ComputerNameIdentifierAlgorithm. Obviously, this is because a computer may only have a single name at any given time. On the other hand, the NicIdentifierAlgorithm can return multiple entries in the list because computers may have multiple Network Interface Cards (NICs). This could occur in a personal computer with built-in wired and wireless network adapters; or it could occur with server that has multiple, redundant network adapters. So following these instructions, the completed class should look something like this:

C#
using System;
using System.Collections.Generic;
using com.softwarekey.Client.Licensing;

namespace YourApplicationsNamespace
{
public class ExampleCustomIdentifierAlgorithm : SystemIdentifierAlgorithm
{
public ExampleCustomIdentifierAlgorithm() : base("ExampleCustom") { }

public override List<SystemIdentifier> GetIdentifiers()
{
List<SystemIdentifier> identifiers = new List<SystemIdentifier>();

identifiers.Add(new ExampleCustomIdentifier("ExampleCustomIdentifier1", "My Example Value"));

return identifiers;
}
}
}
Visual Basic .NET
Imports System
Imports System.Collections.Generic
Imports com.softwarekey.Client.Licensing

Namespace YourApplicationsNamespace
Public Class ExampleCustomIdentifierAlgorithm
Inherits SystemIdentifierAlgorithm

Public Sub New()
MyBase.New("ExampleCustom")
End Sub

Public Overrides Function GetIdentifiers() As List(Of SystemIdentifier)
Dim identifiers As New List(Of SystemIdentifier)

identifiers.Add(New ExampleCustomIdentifier("ExampleCustomIdentifier1", "My Example Value"))

Return identifiers
End Function
End Class
End Namespace

That concludes the steps required to implement your own custom system identifier algorithm.

Using a Custom Identifier Algorithm

Once your class is implemented, all you need to do to use it is add it to the list of algorithms being used in your license implementation. In the PLUSManaged samples and the PLUSManagedGui, this is defined in the SystemIdentifierAlgorithms property in the LicenseConfiguration class. This is then passed in to the License or WritableLicense (or the base class) constructor in your license implementation class. Below is a rough example of how you can modify the LicenseConfiguration class included in the samples to use your new custom algorithm.

C#
internal static List<SystemIdentifierAlgorithm> SystemIdentifierAlgorithms
{
get
{
return new List<SystemIdentifierAlgorithm>(
new SystemIdentifierAlgorithm[] {
new ExampleCustomIdentifierAlgorithm(),
/*All other algorithms you use go here.*/ });
}
}
Visual Basic .NET
Friend Shared ReadOnly Property SystemIdentifierAlgorithms() As List(Of SystemIdentifierAlgorithm)
Get
Return New List(Of SystemIdentifierAlgorithm)(New SystemIdentifierAlgorithm() { New ExampleCustomIdentifierAlgorithm(), _
[All other algorithms used go here] })
End Get
End Property

Accepting User-Defined Input for an Algorithm

If you wish to accept user-defined input, you should omit the step described in the "Using a Custom Identifier Algorithm" section just above. First, you will need to prompt the user to enter the data before initializing the SampleLicense class. In the sample applications, you would do this in the MainForm_Load event handler, just before it loads the license. You would store the data in a private member variable of the MainForm class so that it may be re-used when the application reloads the license, and avoid the need to prompt the user each time this might happen. Next, in the SampleLicense class's constructor, you will want to manually add the identifier to the list of current identifiers. For this example, the code to accomplish this would look something like:

C#
CurrentIdentifiers.Add(new ExampleCustomIdentifier("My Example Value"));
Visual Basic .NET
CurrentIdentifiers.Add(New ExampleCustomIdentifier("My Example Value"))

The hard-coded string, "My Example Value", would instead be replaced by the user-input, which could be passed to the ExampleCustomIdentifier class by adding a new constructor argument and public property (with get and set methods implemented).