ScaleGate.Licensing.SDK 1.0.0

dotnet add package ScaleGate.Licensing.SDK --version 1.0.0
                    
NuGet\Install-Package ScaleGate.Licensing.SDK -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ScaleGate.Licensing.SDK" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ScaleGate.Licensing.SDK" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="ScaleGate.Licensing.SDK" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ScaleGate.Licensing.SDK --version 1.0.0
                    
#r "nuget: ScaleGate.Licensing.SDK, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ScaleGate.Licensing.SDK@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ScaleGate.Licensing.SDK&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=ScaleGate.Licensing.SDK&version=1.0.0
                    
Install as a Cake Tool

ScaleGate.Licensing.SDK

Official .NET client SDK for the Universal Licensing System (ULS) — a multi-tenant SaaS licensing platform by ScaleGate.

Targets .NET Standard 2.0 — works with .NET Framework 4.6.1+, .NET 6/7/8/9, WPF, and WinForms.

Installation

dotnet add package ScaleGate.Licensing.SDK

Quick Start

using Licensing.SDK;

// Build and activate in one call
var client = await LicenseClient
    .Create("my-app", "XXXX-XXXX-XXXX-XXXX")
    .WithApiUrl("https://acme.uls.scalegate.io")
    .WithOfflineValidation(true)
    .WithGracePeriod(7)                  // days of offline use allowed
    .WithAutoRevalidation(true, 30)      // re-check every 30 minutes
    .WithTimeout(15)                     // HTTP timeout in seconds
    .BuildAndActivateAsync();

if (client.IsValid)
{
    // App is licensed — launch main window
    Console.WriteLine($"Plan: {client.CurrentStatus.PlanName}");
    Console.WriteLine($"Expires: {client.CurrentStatus.ExpiryDate:yyyy-MM-dd}");
    Console.WriteLine($"Devices: {client.CurrentStatus.ActiveDevices}/{client.CurrentStatus.MaxDevices}");
}
else
{
    Console.WriteLine($"License error: {client.CurrentStatus.Message}");
}

Builder Methods

Method Description Default
WithApiUrl(string url) ULS tenant API base URL (required)
WithOfflineValidation(bool) Enable AES-256 encrypted offline cache true
WithGracePeriod(int days) Days the app runs offline before blocking 7
WithAutoRevalidation(bool, int min) Background license re-check interval true, 60 min
WithTimeout(int sec) HTTP request timeout 30 sec
ValidateOnStartup(bool) Validate immediately after build true
WithAutoUpdateCheck(string ver, int min) Periodic update checks disabled
WithHttpClient(HttpClient) Inject custom HttpClient (testing)

Build Strategies

// Option 1: Build only (no network call)
var client = LicenseClient.Create(appId, key).Build();

// Option 2: Build + validate (checks license, no device registration)
var client = await LicenseClient.Create(appId, key).BuildAndValidateAsync();

// Option 3: Build + activate (registers device + validates)
var client = await LicenseClient.Create(appId, key).BuildAndActivateAsync();

Core Operations

// Validate (online with offline fallback)
LicenseValidationResult result = await client.ValidateAsync();

// Validate offline only (no network)
LicenseValidationResult offline = await client.ValidateOfflineAsync();

// Activate (register this device)
LicenseValidationResult activation = await client.ActivateAsync();

// Revoke (deregister this device, frees a slot)
LicenseValidationResult revocation = await client.RevokeAsync();

// Renew with a new plan
LicenseValidationResult renewal = await client.RenewAsync(planId: 3);

Events

// License status transitions (Active → GracePeriod → Expired)
client.LicenseStatusChanged += (sender, e) =>
{
    Console.WriteLine($"{e.PreviousStatus} → {e.NewStatus}");
    Console.WriteLine(e.ValidationResult.Message);
};

// After every validation attempt
client.ValidationCompleted += (sender, result) =>
{
    Console.WriteLine($"Valid: {result.IsValid}, Offline: {result.IsOfflineValidation}");
};

// New version detected during auto-update checks
client.UpdateAvailable += (sender, e) =>
{
    Console.WriteLine($"v{e.CurrentVersion} → v{e.LatestVersion}");
    Console.WriteLine(e.ReleaseNotes);
};

// Download progress during updates
client.UpdateProgress += (sender, e) =>
{
    Console.WriteLine($"Stage: {e.Stage}, Progress: {e.ProgressPercentage:F1}%");
};

Self-Update

// Check for updates
UpdateCheckResult update = await client.CheckForUpdateAsync("1.0.0");
if (update.UpdateAvailable)
{
    Console.WriteLine($"New version: {update.LatestVersion}");
    Console.WriteLine(update.ReleaseNotes);
}

// Download update binary
UpdateDownloadResult download = await client.DownloadUpdateAsync("C:\\Updates");
if (download.Success)
    Console.WriteLine($"Downloaded: {download.FilePath}");

// Full self-update: check + download + generate restart script
SelfUpdateResult selfUpdate = await client.PrepareSelfUpdateAsync("1.0.0");
if (selfUpdate.ReadyToApply)
{
    // Replaces current .exe, restarts the app
    SelfUpdater.ApplyAndRestart(
        Environment.ProcessPath,
        selfUpdate.DownloadedFilePath,
        arguments: null);
}

Extension Methods

// Throws LicenseValidationException if invalid
var client = await LicenseClient.Create(appId, key)
    .BuildAndValidateAsync()
    .EnsureValidAsync();

// Throws if activation fails
var client = await LicenseClient.Create(appId, key)
    .Build()
    .EnsureActivatedAsync();

License Status Values

Status Meaning
Active Valid and online-verified
GracePeriod Expired but within offline grace window
Expired Past expiry + grace period
Inactive Deactivated by admin
NotFound Invalid license key
DeviceNotRegistered Device not activated
DeviceLimitReached Too many devices registered
InvalidApp License not issued for this app
ValidationRequired Must validate online
NetworkError Could not reach the API
ServerError API returned an error

Device Fingerprinting

The SDK automatically generates a hardware fingerprint from:

  • CPU ID (via WMI)
  • Motherboard serial number (via WMI)
  • Windows Machine SID

The fingerprint is SHA-256 hashed and cached locally. Use DeviceFingerprint.RegenerateFingerprint() to force a new fingerprint if hardware changes.

Offline Cache

When WithOfflineValidation(true) is set, the SDK stores an AES-256 encrypted license cache at:

%LocalAppData%\Licensing\{appId}\license.dat

The cache includes the last successful validation result, expiry date, and plan details. During offline periods, the SDK validates against this cache and respects the configured grace period.

Requirements

  • .NET Standard 2.0 compatible runtime
  • Windows (required for WMI-based hardware fingerprinting)
  • Network access to your ULS tenant API (for online validation)

License

MIT License - Copyright (c) 2026 Wise & Agile Solutions

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 84 4/3/2026

Initial release — license activation, validation, offline cache, grace period, auto-revalidation, self-update, and device management.