Home

Awesome

TrialMaker: Trial & Premium Licensing for .NET Software

Purchase via Gumroad Purchase via Gumroad Purchase via Gumroad Purchase via Gumroad License

TrialMaker is a premium library that provides trial licensing for .NET applications. It provides a simplified and easy way to integrate secure free-trial license generation and copy protection features. It also supports premium offline license generation for expired free-trials with its own License Generator utility.

<div align="center">

trial-maker-logo

</div>

Installation

To install via the NuGet Package Manager Console, run:

Install-Package TrialMaker.Licensing.Preview

If you have a license, install the premium version by running:

Install-Package TrialMaker.Licensing.Premium

Features

✔️ Security checks

Demo

TrialMaker includes a sample C# demo project that will help you easily get started. Below is a sample preview of the running demo and the License Generator utility in-part:

To know more about the License Generator utility, please head over to the section Activating Premium Licenses.

trial-maker-demo

🍉 Demo limitations

TrialMaker's demo library let's any interested developers test its core features. Once satisfied, you can go ahead and purchase the premium version that removes all limitations, allowing you to build distributable and production-ready applications.

The limitations include:

To get the full-featured library, please consider purchasing a license. Once purchased, you will also receive the License Generator utility for generating premium licenses.

🚀 Activating your license

After purchasing a license and installing the premium version in your project, you can activate your license by:

In case you face any issues, please feel free to ask for help anytime from the Need Help discussions area.

Usage

First, ensure you import the library's core namespaces after installation:

using WK.Libraries.TrialMakerNS;
using WK.Libraries.TrialMakerNS.Models;

...then instantiate the core class and add the following code:

var tm = new TrialMaker();

// Add your product's information.
tm.ProductInfo = new ProductInfo()
{
    ID = "#MyVeryUniqueProductID#",              // A unique product ID string.
    Name = "My App",                             // Your product's name.
    Owner = "My Company",                        // Your company or alias name.   
    TotalDays = 30,                              // How many trial days?
    PurchasePage = "https://myapp.com/purchase"  // Your product's purchase page (optional).
};

// This validates an existing license or creates a new one.
License lic = tm.Validate();

if (lic.Status == LicenseStatus.Active)
{
    if (lic.Type == LicenseTypes.FreeTrial)
    {
        // Free trial license.
    }
    else if (lic.Type == LicenseTypes.Premium)
    {
        // Premium license.
    }
}
else if (lic.Status == LicenseStatus.Expired)
{
    // The license has expired.
}
else if (lic.Status == LicenseStatus.Invalid)
{
    // The installed license is invalid.
    // Use 'ValidationErrors' property to determine which errors were captured.
    // You can choose to exit your application to prevent usage.
}

Simple huh! That's just about it for the basic implementation of licensing in your apps.

Now let's break it down to understand what happens in each step...

Breakdown

Please note that in all our examples, we will be using the tm variable which is an instance of the TrialMaker class.

1. Adding product information

All licenses created will require the following information:

  1. A unique product ID.
  2. The product name.
  3. The product owner, team or company.
  4. The number of trial days.
  5. (Optional) A purchase link to direct potential clients.

With this information, licenses can be validated and verified for use by any client.

The product ID is an important property since it uniquely sets it apart from all other products. Ensure you store the product ID somewhere safe e.g. in a locally encrypted database or in your project's Resources. If you'll be storing it inside your project's Resources, please ensure you obfuscate the Resources before deployment.

Here's a code snippet:

tm.ProductInfo = new ProductInfo()
{
    ID = "#MyVeryUniqueProductID#"               // A unique product ID string.
    Name = "My App",                             // Your product's name.
    Owner = "My Company",                        // Your company or alias name.
    TotalDays = 30,                              // How many trial days?
    PurchasePage = "https://myapp.com/purchase"  // Your product's purchase page (optional).
};

Also and more importantly, if you have the License Generator utility and will be generating premium licenses for clients, ensure you provide the same product name and ID when adding your product.

2. Validating licenses

This is the core method that lets you validate any new or existing licenses generated for your clients. It allows for both creation and validation of licenses thus simplifying creation of new licenses or, at a similar level, validation of existing ones.

You only need to add one line of code:

License lic = tm.Validate();  // A TrialMaker license is returned after validation.

From here, we proceed to validating the license based on the returned License object.

The License.Status property

The most crucial section in the returned License object is the Status property. There are currently 3 license status options provided:

To determine the type of license installed, use the License.Type property:

if (lic.Status == LicenseStatus.Active)
{
    if (lic.Type == LicenseTypes.FreeTrial)
    {
        // Free trial.
    }
    else if (lic.Type == LicenseTypes.Premium)
    {
        // Premium.
    }
}

Premium licenses can be generated using the License Generator utility. For more info, please checkout the section Activating Premium Licenses.

To activate a premium license, use the Activate(string license) method. This method accepts a secured license string as an argument:

var lic = tm.Activate("provide the secured license");

if (lic.Status == LicenseStatus.Active)
{
    // The license has been activated and installed.
}
else if (lic.Status == LicenseStatus.Invalid)
{
    // Use the 'ValidationErrors' property to determine which errors were raised.
    string errors = string.Join(",\n", tm.ValidationErrors);
    MessageBox.Show(errors);
}

You can also check whether the user is trying the application for the first time using the License.FirstTime property. This could be useful if you wish to welcome any potential clients or even showcase premium features to encourage upgrading to the premium version:

if (lic.Status == LicenseStatus.Active)
{
    if (lic.Type == LicenseTypes.FreeTrial)
    {
        if (lic.FirsTime)
        {
            // This is a first-time free trial user.
        }
    }
}

In place of the License.FirstTime property which is only available after validation, you can also use the library's LicenseExists property:

if (tm.LicenseExists == false)
{
    // Show e.g. a welcome dialog.
}

Checking validation errors

For licenses deemed invalid, we can make use of the ValidationErrors property that TrialMaker provides to determine the errors raised upon validation. The ValidationErrors property stores a collection of all possible errors captured during validation. They are:

ErrorDescription
SystemBackdatedThe System Date/Time has been backdated.
LicenseEmptyThe license is empty.
LicenseCorruptedThe license is corrupted.
InvalidHardwareIDThe device Hardware ID does not match the Hardware ID registered with the license.
InvalidProductIDThe license's product ID does not match the original product ID.
InvalidProductNameThe license's product name does not match the original product name.

These errors have been specifically provided to enable copy-protection and promote license integrity when distributing your applications.

As a safety mechanism, if any error is raised in your application, you can exit it to prevent further use until the errors(s) have been resolved. You can also provide an error reporting feature that allows clients to submit errors if they were not malicious in nature.

Here's an example displaying the various errors that may have been raised:

if (lic.Status == LicenseStatus.Invalid)
{
    string errors = string.Join(",\n", tm.ValidationErrors);
    MessageBox.Show(errors);
    
    // You can choose to exit your application to prevent usage.
    // Application.Exit();
}

To verify whether a specific error was raised, use the Contains method as provided in list collections:

if (lic.Status == LicenseStatus.Invalid)
{
    if (tm.ValidationErrors.Contains(ValidationErrors.SystemBackdated))
    {
        MessageBox.Show("Please do not backdate your system.");
        // Application.Exit();
    }
}

You can also refer to the sample demo for a live working preview.

The License class

Below are the properties in a TrialMaker License class:

PropertyDescription
TypeGets or sets the license type.
StatusGets or sets the license status.
CompanyGets or sets the licensed owner or company.
ProductGets or sets the product name.
ProductIDGets or sets the unique product ID.
LicenseKeyProvides an auto-generated free-trial license key based on the MD5 hash of the customer's Hardware ID.
HardwareIDsGets or sets the list of devices that can be activated based on their Hardware IDs.
ActivationsGets the number of activations available based on the list of device Hardware IDs.
ActivationDateGets or sets the date the license was created and activated.
ExpiryDateGets the date the license is set to expire.
LastUsedGets or sets the date the license was last used. This is only updated if the TrialMaker.TrackUsage property is set to true.
TotalDaysGets or sets the total number of days assigned to the customer.
RemainingDaysGets the number of days remaining before the license expires.
IsValidGets a value indicating whether the license is valid based on a device's Hardware ID.
FirstTimeVerifies whether this is a first-time user, meaning their license has been created for the first time.
UsesGets the number of times the license has been used. This is synonymous with the number of times the application has been run. However once a premium license has been activated, the usage count will be reset to zero to initiate a new counting. This is only updated if the TrialMaker.TrackUsage property is set to true.
DeviceGets the user device information.

3. Tracking usage of licenses

Tracking number of uses

As pointed out earlier, with TrialMaker, you can easily track the number of uses per customer license. We do this by enabling the property TrackUsage in TrialMaker and using the License.Uses property. You can also get when last the license was used using the License.LastUsed property which is of a DateTime type.

Here's an example:

// Enable usage tracking.
tm.TrackUsage = true;

// Set maximum usage count.
int maxUses = 12;

if (lic.Status == LicenseStatus.Active)
{
    if (lic.Uses == maxUses)
    {
        MessageBox.Show(
            "You have exceeded the no. of uses." +
            "Please purchase a full version.");
    }
    else
    {
        MessageBox.Show($"You have {12 - lic.Uses} remaining.");
    }
}

You can also check the last used date/time using the License.LastUsed property:

MessageBox.Show($"Last Used: {lic.LastUsed}");

Tracking usage time

To track how much time is being used, simply enable the property TrialMaker.TrackTime. This will then allow you to use the TrialRuntime event that tracks the application's running timespan:

// Enable time tracking.
tm.TrackTime = true;

// Add time tracking event.
tm.TimeTracking += TimeTracking;

private void TimeTracking(object sender, TrialMaker.TimeTrackingEventArgs e)
{
    string time = e.TimeSpan.ToString(@"hh\:mm\:ss");
}

With this you can choose to limit how much time clients will use your application in free-trial mode:

private void TimeTracking(object sender, TrialMaker.TimeTrackingEventArgs e)
{
    if (e.TimeSpan.Hours == 2)
    {
        // If time used exceeds 2 hours, inform the user to upgrade.
        MessageBox.Show(
            "Your trial time limit has reached." + 
            "Please purchase a full version.");
	}
}

As a side note, always ensure you inform your users if at all you prefer to restrict how much time or the number of uses for your application(s) in free trial mode.

Additional features

1. Getting the Hardware ID

You can get a client's machine Hardware ID using the static TrialMaker.HardwareID property:

string hid = TrialMaker.HardwareID;

This property auto-generates a 36-character unique machine code based on the client machine's hardware properties.

Here's a machine code sample: LIITOJVC-HREOTRVU-NTHNQUWT-UQABNVGK-BGXH

2. Checking if a license exists

To check whether a license exists (free-trial or premium), simply use the LicenseExists property:

bool exists = tm.LicenseExists;

3. Checking for Network availability

You can determine whether an Internet connection is available using the IsNetworkAvailable property:

bool netAvailable = tm.IsNetworkAvailable();

4. Checking if system date is backdated

To manually check if the current system date is backdated, use the IsSystemBackdated() method:

bool isBackdated = tm.IsSystemBackdated();

5. Checking if system date is correct

To manually check if the current system date is correct (up-to-date), use the IsSystemDateCorrect() method:

bool isDateCorrect = tm.IsSystemDateCorrect();

6. Opening the purchase page

To open the product's purchase page as registered in the ProductInfo property, use the OpenPurchasePage() method:

tm.OpenPurchasePage();

This will open the link using the default browser.

You can also open other links using the method OpenLink(string url).

7. Displaying a product title

TrialMaker helps model a title message for use in your application using the ModelProductTitle() method:

model-product-title

string title = tm.ModelProductTitle();

// Format: "Product (LicenseType)", e.g. "My App (30-day free trial)" or "My App (Premium)"

8. Displaying a license expiration message

TrialMaker also helps model an expiration message using the ModelExpirationMessage() method:

model-product-title

string title = tm.ModelExpirationMessage();

// Format: "Evaluation period expires on {dddd dd MMMM, yyyy}" 
// e.g. "Evaluation period expires on Wednesday 13th August, 2020"

Activating premium licenses

If you never activated your license after installing TrialMaker, License Generator will still request for activation.

TrialMaker includes an offline and powerful license generation utility that lets you generate premium licenses for converting free-trial users to premium clients. You can provide single device activations or multi-device activations, meaning that a client can either receive a single license for one device or a single license for multiple devices:

trial-maker-demo

We will now discuss how the License Generator works...

Features

Usage

The utility has four main sections:

  1. Device Information: This is where you provide the client's generated Hardware ID that will be used to lock the license to their machine. You can also provide a list of Hardware IDs from the various devices a client will be using the application:

    hid-section

  2. License Information: Here, you will provide the name of the product being licensed, the client's name or company, and (optionally) choose to limit the number of days for using the license - this may be necessary if your product is subscription-based, e.g yearly:

    hid-section

    Here you can also add a product to the list of products you're currently selling to make it easier when licensing multiple clients. To do this, simply click on the Add icon button to the left of the products combo box; a dialog will appear allowing you to add your product(s) to the local db:

    hid-section

  3. License Generation: This section is mainly for generation of licenses based on the provided inputs. You can also copy the license generated and/or save the license as a file to send to the client for activation. Sending licenses as files is a preferred option to make the activation process easier for clients.

    hid-section

  4. Clients Database: This section mainly covers the clients management aspect. Whenever you generate a premium license, it is automatically added to the local Clients.db database located in the same folder as the utility. In this section, you can view your list of clients, search for a particular client, view their license details, and/or delete their records:

    hid-section

    To search for clients, use the search input located at the top. To specify the search option, use the combo box to the right of the search input:

    hid-section

You can expand or collapse the Clients Database section using the expand/collapse icon: search-clients

That's about it on License Generator. More updates and improvements are sure to come with every release.

License

TrialMaker and its sources are governed under a Proprietary License. The demo however is under an MIT license.

Feel free to reach out via email for any consultations: wilskym[at]live[dot]com.

You can also get the complete source code if you'd love to build your own thing or extend the product even further. By purchasing either a license or the sources, you go a long way in supporting my projects and libraries. Many thanks!

Made with 💛 by Willy Kimura