Interface ILicenseProvider
Defines methods for license checks.
Namespace: Sartorius.SAF.Licensing
Assembly: Sartorius.SAF.Licensing.dll
Syntax
[InheritedExport]
public interface ILicenseProvider : IDisposable
Remarks
If you get a System.ComponentModel.Composition.ImportCardinalityMismatchException when trying to import the ILicenseProvider interface, you have to add an actual license provider implementation via nuget. E.g. Sartorius.Licensing.Mirage.
A license provider can require a configuration before it can be imported. For the configuration options see the specific license provider implementation you are using. You will get a System.ComponentModel.Composition.CompositionException during runtime when a required configuration object is missing. When required configuration entries are missing in the configuration object a System.Configuration.ConfigurationErrorsException is thrown at runtime. A class deriving from LicenseConfiguration will be exported automatically by using an inherited export.
A license provider can provide a typed configuration object you can derive from, allowing for a more convenient configuration workflow.
When using the MirageLicenseProvider in combination with activation keys see ISerialLicenseProvider for the correct licensing workflow.
Examples
The following example shows how to import a license provider via MEF.
[ImportingConstructor]
public LicensingExamples(ILicenseProvider licenseProvider)
{
this.licenseProvider = licenseProvider;
}
The following example shows how to configure the Mirage license provider (MirageLicenseProvider) by deriving from LicenseConfiguration.
public class MyConfiguration : LicenseConfiguration
{
public MyConfiguration()
{
Add("ReadKey", LicensingTools.ReadKey);
}
}
Generally a license provider will also provide a typed configuration object which can be used more conveniently. The following example shows how to configure the Mirage license provider by deriving from MirageLicenseConfiguration.
public class MyTypedConfiguration : MirageLicenseConfiguration
{
public override SecureString ReadKey => LicensingTools.ReadKey;
}
The following example shows how to check for the availability of a feature.
var checkoutInfo = this.licenseProvider.Checkout("Feature 1");
if (!checkoutInfo.State.HasFlag(FeatureState.Licensed))
{
// Stop application with "no license available" message
checkoutInfo.Dispose();
}
else if (checkoutInfo.State.HasFlag(FeatureState.Demo))
{
// Show demo nag screen
}
The following example shows how to check for the availability of a feature and the available count.
var checkoutInfo = this.licenseProvider.Checkout("Units", 6);
if (checkoutInfo.State.HasFlag(FeatureState.Licensed) && checkoutInfo.State.HasFlag(FeatureState.InsufficientLicense))
{
// too many units
var excessiveUnitCount = currentUnitCount - checkoutInfo.AvailableLicenses;
try
{
// ask user to delete excessive units until only licensed units are available.
// or deactivate units
// If the application does now use only the AvailableLicenses you can proceed.
// If your application closes due to not enough licenses, it should return the license (e.g. by disposing the CheckoutInfo).
}
catch
{
// either call
checkoutInfo.Dispose();
// or explicitly check-in the checked out licenses
// this.licenseProvider.Checkin("Units", unitInfo.AvailableLicenses);
throw;
}
}
else if (checkoutInfo.State.HasFlag(FeatureState.Demo))
{
// Show demo nag screen
}
The following example shows how to read available hardware ids.
try
{
// get all available harware ids
var result = this.keysLicenseProvider.GetHardwareIds();
// get needed hardware ids
result = this.keysLicenseProvider.GetHardwareIds(1, 2, -3);
}
catch (KeyNotFoundException)
{
// TODO: exception should provide info if requested id is out of the supported range (in this case -3).
// show error message to the user
}
catch (InvalidLicenseException)
{
// TODO: exception should provide info about the license file is damaged or incomplete.
// show error message to the user
}
catch (LicenseFileAccessException)
{
// TODO: exception should provide info about the license file could not be accessed.
// show error message to the user
}
catch (SystemDateChangedException)
{
// TODO: exception should provide info about the system date was tampered with and the application is locked.
// show error message to the user
}
catch (LicenseException)
{
// TODO: An unknown exception occurred. See the <see cref="Exception.InnerException" /> for details..
// show error message to the user
}
The following example shows how to read license file information.
public String FormatLicenseFileInfo()
{
var sb = new StringBuilder();
try
{
var info = this.licenseProvider.GetLicenseFileInfo();
sb.AppendLine($"The license file {info.FileName} contains the following information:");
foreach (var featureInfo in info.FeatureInfos)
{
sb.AppendLine($"Feature '{featureInfo.Name}' ({featureInfo.ID}) has {featureInfo.RemainingLicenses} licenses");
if (featureInfo.State.HasFlag(FeatureState.Demo))
{
sb.AppendLine($"The feature is a demo");
}
if (featureInfo.ExpirationDate.HasValue)
{
sb.AppendLine($"It expires on {featureInfo.ExpirationDate.Value}");
}
}
}
catch (InvalidLicenseException)
{
sb.Append("The license file is damaged. Please contact your administrator.");
}
catch (LicenseFileAccessException)
{
sb.Append("The license file is not accessible. Please contact your administrator.");
}
catch (SystemDateChangedException)
{
sb.Append("The system date was tampered with and the application is locked");
}
catch (LicenseException)
{
sb.AppendLine("An unexpected license error occured.");
}
return sb.ToString();
}
The following example shows how to use the LicenseChanged event to handle license changes.
[ImportingConstructor]
public LicenseConsumer(ILicenseProvider licenseProvider)
{
this.licenseProvider = licenseProvider ?? throw new ArgumentNullException(nameof(licenseProvider));
this.licenseProvider.LicenseChanged += OnLicenseChanged;
}
private void OnLicenseChanged(Object sender, LicenseEventArgs licenseEventArgs)
{
switch (licenseEventArgs.Action)
{
case LicenseEventAction.Expired:
// one or more feature licenses have expired
// this is called from a worker thread
// remove the features from the application
RemoveFeatures(licenseEventArgs.Removed);
// Show information to the user about the expired features
ShowInfo(licenseEventArgs.Removed);
break;
case LicenseEventAction.Changed:
// a change of license occured. This happens when keys are applied.
// add the feature functionality to the application
AddFeatures(licenseEventArgs.Added);
// remove features that are no longer available
RemoveFeatures(licenseEventArgs.Removed);
// update feature functionality for changed features (e.g. expiration date has been updated, license count has been updated)
ChangeFeatures(licenseEventArgs.Changed);
break;
case LicenseEventAction.Error:
// an error occured when there was a timed check for expired modules
// throw the exception in the UI thread and let the global exception handler take care of application shutdown.
Application.Current.Dispatcher.BeginInvoke(new Action(((ErrorLicenseEventArgs) licenseEventArgs).Throw));
// or use ErrorLicenseEventArgs::Exception to handle the exception here.
// keep in mind this runs on a background thread.
break;
default:
throw new ArgumentOutOfRangeException(nameof(licenseEventArgs));
}
}
The following example shows how to read license feature information.
try
{
var featureInfo = this.licenseProvider.GetFeatureInfo("feature id");
if (featureInfo.RemainingLicenses <1)
{
// do something
}
// check other properties of featureInfo.
}
catch (FeatureNotFoundException)
{
// show corresponding info
}
//
// catch any other exceptions (see definition of the ILicenseProvider)
//
Methods
View SourceApplyLicense(Stream)
Applies the license from the specified stream.
Declaration
void ApplyLicense(Stream stream)
Parameters
Type | Name | Description |
---|---|---|
System.IO.Stream | stream | The stream of the license file. |
Exceptions
Type | Condition |
---|---|
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
ApplyLicense(String)
Applies the license from the specified file path.
Declaration
void ApplyLicense(string path)
Parameters
Type | Name | Description |
---|---|---|
System.String | path | The path to the new license file. |
Exceptions
Type | Condition |
---|---|
System.IO.FileNotFoundException | The file specified by |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
Checkin(String)
Checks in the feature with the specified feature identifier.
Declaration
void Checkin(string featureId)
Parameters
Type | Name | Description |
---|---|---|
System.String | featureId | The identifier of the feature to check in. |
Exceptions
Type | Condition |
---|---|
System.ArgumentNullException |
|
FeatureNotFoundException | The feature with the specified id does not exist. |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
Checkin(String, Int32)
Checks in the feature with the specified feature identifier and count.
Declaration
void Checkin(string featureId, int count)
Parameters
Type | Name | Description |
---|---|---|
System.String | featureId | The identifier of the feature to check in. |
System.Int32 | count | The count of licenses to check in for the specified feature. |
Exceptions
Type | Condition |
---|---|
System.ArgumentException | The |
System.ArgumentNullException |
|
FeatureNotFoundException | The feature with the specified id does not exist. |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
Checkout(String)
Checks out the feature with the specified identifier.
Declaration
CheckoutInfo Checkout(string featureId)
Parameters
Type | Name | Description |
---|---|---|
System.String | featureId | The identifier of the feature to check out. |
Returns
Type | Description |
---|---|
CheckoutInfo | A CheckoutInfo containing info about the checkout process. |
Exceptions
Type | Condition |
---|---|
System.ArgumentNullException |
|
FeatureNotFoundException | The feature with the specified id does not exist. |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
Checkout(String, Int32)
Checks out the feature with the specified identifier and the specified count.
Declaration
CheckoutInfo Checkout(string featureId, int count)
Parameters
Type | Name | Description |
---|---|---|
System.String | featureId | The identifier of the feature to check out. |
System.Int32 | count | The count of licenses to check out for the specified feature. |
Returns
Type | Description |
---|---|
CheckoutInfo | A CheckoutInfo containing info about the checkout process. |
Exceptions
Type | Condition |
---|---|
System.ArgumentException | The |
System.ArgumentNullException |
|
FeatureNotFoundException | The feature with the specified id does not exist. |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
GetFeatureInfo(String)
Gets the feature information for the specified feature.
Declaration
FeatureInfo GetFeatureInfo(string featureId)
Parameters
Type | Name | Description |
---|---|---|
System.String | featureId | The identifier of the feature. |
Returns
Type | Description |
---|---|
FeatureInfo | The information for the specified feature. |
Exceptions
Type | Condition |
---|---|
System.ArgumentNullException |
|
FeatureNotFoundException | The feature with the specified id does not exist. |
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
GetHardwareIds(Int32[])
Gets the hardware identifiers for the specified types.
Declaration
IEnumerable<HardwareId> GetHardwareIds(params int[] ids)
Parameters
Type | Name | Description |
---|---|---|
System.Int32[] | ids | The identifiers of the HardwareIds to get. If this is empty all hardware ids will be returned. |
Returns
Type | Description |
---|---|
System.Collections.Generic.IEnumerable<HardwareId> | All hardware ids or the hardware ids identified by |
Exceptions
Type | Condition |
---|---|
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
System.Collections.Generic.KeyNotFoundException | The one of the requested ids is out of the supported range. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
GetLicenseFileInfo()
Gets information about the license file.
Declaration
LicenseFileInfo GetLicenseFileInfo()
Returns
Type | Description |
---|---|
LicenseFileInfo | An instance of LicenseFileInfo that contains information about the license file. |
Examples
The following example shows how to read license file information.
public String FormatLicenseFileInfo()
{
var sb = new StringBuilder();
try
{
var info = this.licenseProvider.GetLicenseFileInfo();
sb.AppendLine($"The license file {info.FileName} contains the following information:");
foreach (var featureInfo in info.FeatureInfos)
{
sb.AppendLine($"Feature '{featureInfo.Name}' ({featureInfo.ID}) has {featureInfo.RemainingLicenses} licenses");
if (featureInfo.State.HasFlag(FeatureState.Demo))
{
sb.AppendLine($"The feature is a demo");
}
if (featureInfo.ExpirationDate.HasValue)
{
sb.AppendLine($"It expires on {featureInfo.ExpirationDate.Value}");
}
}
}
catch (InvalidLicenseException)
{
sb.Append("The license file is damaged. Please contact your administrator.");
}
catch (LicenseFileAccessException)
{
sb.Append("The license file is not accessible. Please contact your administrator.");
}
catch (SystemDateChangedException)
{
sb.Append("The system date was tampered with and the application is locked");
}
catch (LicenseException)
{
sb.AppendLine("An unexpected license error occured.");
}
return sb.ToString();
}
Exceptions
Type | Condition |
---|---|
InvalidLicenseException | The license file is damaged or incomplete. |
InvalidLicenseFileException | The license file is not a valid license file. |
LicenseException | An unknown exception occurred. See the System.Exception.InnerException for details. |
LicenseFileAccessException | The license file could not be accessed. |
SystemDateChangedException | The system date was tampered with and the application is locked. |
Events
View SourceLicenseChanged
Occurs when the license is changed due to the expiration of features or application of a new license or license keys.
Declaration
event EventHandler<LicenseEventArgs> LicenseChanged
Event Type
Type | Description |
---|---|
System.EventHandler<LicenseEventArgs> |
Remarks
The event can occur when timed licenses (e.g. demo or subscription licenses) expire. It will occur at the time the license expires or shortly after. For many license providers (e.g. Mirage LicProtector) this kind of expiration will occur at midnight.
The event can also occur when a license is changed by applying a license file (by using ApplyLicense(String) or ApplyLicense(Stream)) or when license keys are applied (by using ApplyActivationKeys(String[])). In these cases the event is directly while the methods triggering the license change are executed.
The events will always be raised on the thread that first did subscribe to the event.
Implementations of ILicenseProvider should always use weak event references to prevent routing event subscribers.
Examples
The following example shows how to use the LicenseChanged event to handle license changes.
[ImportingConstructor]
public LicenseConsumer(ILicenseProvider licenseProvider)
{
this.licenseProvider = licenseProvider ?? throw new ArgumentNullException(nameof(licenseProvider));
this.licenseProvider.LicenseChanged += OnLicenseChanged;
}
private void OnLicenseChanged(Object sender, LicenseEventArgs licenseEventArgs)
{
switch (licenseEventArgs.Action)
{
case LicenseEventAction.Expired:
// one or more feature licenses have expired
// this is called from a worker thread
// remove the features from the application
RemoveFeatures(licenseEventArgs.Removed);
// Show information to the user about the expired features
ShowInfo(licenseEventArgs.Removed);
break;
case LicenseEventAction.Changed:
// a change of license occured. This happens when keys are applied.
// add the feature functionality to the application
AddFeatures(licenseEventArgs.Added);
// remove features that are no longer available
RemoveFeatures(licenseEventArgs.Removed);
// update feature functionality for changed features (e.g. expiration date has been updated, license count has been updated)
ChangeFeatures(licenseEventArgs.Changed);
break;
case LicenseEventAction.Error:
// an error occured when there was a timed check for expired modules
// throw the exception in the UI thread and let the global exception handler take care of application shutdown.
Application.Current.Dispatcher.BeginInvoke(new Action(((ErrorLicenseEventArgs) licenseEventArgs).Throw));
// or use ErrorLicenseEventArgs::Exception to handle the exception here.
// keep in mind this runs on a background thread.
break;
default:
throw new ArgumentOutOfRangeException(nameof(licenseEventArgs));
}
}