Licensing Integration
and
Analytics Integration
Introduction
This article shows you how to use an example code project as the basis for adding Zentitle Licensing to your own application using Visual Studio and C# or VB.NET.
Before following this documentation, please be sure to first create and download your custom Licensing/Analytics library - see section Download the required Zentitle library for how to do this.
Download the Example Applications
Release Notes (Please always check the release notes for the latest updates)
You can download the C# SDK directly from the Zentitle V10 dashboard as described here.
Getting Started with Visual Studio
Download the required example application from the attached link and extract to a suitable folder.
C# Example:
Double-clicking the project file ShaferExample.csproj will open the project in Visual Studio and create a solution from this project.
VB.Net Example:
Double-clicking the project file VBShaferExample.vbproj will open the project in Visual Studio and create a solution from this project.
Before building this solution, ensure that the ShaferFilechck.dll library is in the same folder as your application's executable. In Visual Studio, this will, by default, be either the /bin/release or /bin/debug folder depending on whether your build configuration is or debug or release.
C# Example:
VB.Net Example:
Code Integration Walkthrough - Licensing
1. Create your Public Class
The ShaferExample class is our example public class - scrolling to the top of this class you will find a number of variables which should be initialized correctly. You should also instantiate the Shafer class and assign this to a class variable:
C# Example - Initialising the class variables
public partial class ShaferExample : Form
{
Shafer oShafer = new Shafer();
string Username = "";
int ShaferError = 0;
int CustomerID = 3183; //**** REPLACE WITH YOUR CUSTOMERID
int ProductID = 100; //**** REPLACE WITH YOUR PRODUCTID
UInt32 SecurityConstantX = 100; //**** REPLACE WITH YOUR Security Constant X
UInt32 SecurityConstantY = 600; //**** REPLACE WITH YOUR Security Constant Y
UInt32 SecurityConstantZ = 400; //**** REPLACE WITH YOUR Security Constant Z
UInt32 UserLoginTxnID = 0;
Timer timer = new Timer(); //Timer to periodically check License
public Boolean JustExit = false;
public Boolean AppStarted = false;
VB Example - Initialising the class variables
Public Class ShaferExample
Private oShafer As New Shafer()
Private Username As String = ""
Private ShaferError As Integer = 0
Private CustomerID As Integer = 3183
'**** REPLACE WITH YOUR CUSTOMERID
Private ProductID As Integer = 100
'**** REPLACE WITH YOUR PRODUCTID
Private SecurityConstantX As UInt32 = 100
'**** REPLACE WITH YOUR Security Constant X
Private SecurityConstantY As UInt32 = 600
'**** REPLACE WITH YOUR Security Constant Y
Private SecurityConstantZ As UInt32 = 400
'**** REPLACE WITH YOUR Security Constant Z
Private UserLoginTxnID As UInt32 = 0
Private Shared timer As New Timer()
'Timer to periodically check License
Public JustExit As [Boolean] = False
Public AppStarted As [Boolean] = False
Within your Form Load or Application Initialize Event, add code to call the following functions located in the Shafer.cs (oShafer Object) class
2. Call your Initialise Method
C# Example - Load / Init Event
public int init(int CustomerID, int ProductID, UInt32 X, UInt32 Y, UInt32 Z, ref bool BadImage)
{
int ShaferError = 0;
//Create a random number between 1 and 500 for the Security Constants
Random rnd = new Random();
UInt32 SecurityRandom = (UInt32)rnd.Next(1, 500); // creates a number between 1 and 500
//If using security constants then Calculate Offset and pass to Init
if (X != 0 && Y != 0 && Z != 0)
{
//Calculate Offset
SecurityOffset = CalculateSecurityOffSet(SecurityRandom, X, Y, Z);
}
//Create parameters key/value pair structure
Dictionary<string, string> xParms = new Dictionary<string, string>();
//Advnaced settings, for normal operation leave as defaults
xParms.Add("LogLevel", "4"); //set log level, please see documentation
xParms.Add("OfflineMode", "0"); //Select Offline mode, please see documentation
xParms.Add("LogDir", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Nalpeiron"); //Default Directory, change to specify different location
xParms.Add("LogQLen", "300"); //please see documentation
xParms.Add("CacheQLen", "25"); //please see documentation
xParms.Add("SoapThreadsMin", "10"); //please see documentation
xParms.Add("SoapThreadsMax", "10"); //please see documentation
xParms.Add("ProxyIP", ""); //InternetConnection Proxy IP address, if required
xParms.Add("ProxyPort", ""); //InternetConnection Proxy Port, if required
xParms.Add("ProxyUsername", ""); //InternetConnection Proxy Username, if required
xParms.Add("ProxyPassword", ""); //InternetConnection Proxy Password, if required
xParms.Add("NSAEnabled", "1"); //Enable Analytics
xParms.Add("NSLEnabled", "1"); //Enable Licensing
xParms.Add("SecurityValue", SecurityRandom.ToString()); //Security Offset if enabled, or 0
xParms.Add("WorkDir", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Nalpeiron"); //Work Directory
xParms.Add("NSLConnTO", "0"); // NSL connection timeout
xParms.Add("NSLTransTO", "0"); // NSL transaction timeout
xParms.Add("NSAConnTO", "0"); // NSA connection timeout
xParms.Add("NSATransTO", "0"); // NSA transaction timeout
xParms.Add("DaemonIP", ""); //Daemon IP
xParms.Add("DaemonPort", ""); //Daemon Port
xParms.Add("DaemonUser", ""); //Daemon User
xParms.Add("DaemonPass", ""); //Daemon Password
//Create the XML doc to pass parameters
string xmlParms = ConstructXMLVariableTag(xParms, "SHAFERXMLParams");
//Initialise NSA and record Application Start
// Convert string to byte array for Unicode compatibvility
byte[] UTFxmlParms = Encoding.UTF8.GetBytes(xmlParms == null ? "" : xmlParms);
try
{
ShaferError = NalpLibOpen(UTFxmlParms);
if (ShaferError < 0)
{
return ShaferError;
}
}
catch (System.BadImageFormatException e)
{
BadImage = true;
return ShaferError;
}
//Validate the DLL (Check to see if correct DLL for This Customer and Product)
ShaferError = NSAValidateLibrary(CustomerID, ProductID);
if (ShaferError < 0)
{
return ShaferError;
}
return ShaferError;
}
VB Example - Load / Init Event
Public Function init(ByVal CustomerID As Integer, ByVal ProductID As Integer, ByVal X As UInt32, ByVal Y As UInt32, ByVal Z As UInt32, ByRef BadImage As Boolean) As Integer
Dim ShaferError As Integer = 0
Dim rnd As New Random()
Dim SecurityRandom As UInt32 = CType(rnd.Next(1, 500), UInt32)
'If using security constants then Calculate Offset and pass to Init
If X <> 0 AndAlso Y <> 0 AndAlso Z <> 0 Then
'Create a random number between 1 and 500 for the Security Constants
' creates a number between 1 and 500
'Calculate Offset
SecurityOffset = CalculateSecurityOffSet(SecurityRandom, X, Y, Z)
End If
'Create parameters key/value pair structure
Dim xParms As New Dictionary(Of String, String)()
'Advanced settings, for normal operation leave as defaults
xParms.Add("LogLevel", "4")
'set log level, please see documentation
xParms.Add("OfflineMode", "0")
'Select Offline mode, please see documentation
xParms.Add("LogDir", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\Nalpeiron")
'Default Directory, change to specify different location
xParms.Add("LogQLen", "300")
'please see documentation
xParms.Add("CacheQLen", "25")
'please see documentation
xParms.Add("SoapThreadsMin", "10")
'please see documentation
xParms.Add("SoapThreadsMax", "10")
'please see documentation
xParms.Add("ProxyIP", "")
'InternetConnection Proxy IP address, if required
xParms.Add("ProxyPort", "")
'InternetConnection Proxy Port, if required
xParms.Add("ProxyUsername", "")
'InternetConnection Proxy Username, if required
xParms.Add("ProxyPassword", "")
'InternetConnection Proxy Password, if required
xParms.Add("NSAEnabled", "1")
'Enable Analytics
xParms.Add("NSLEnabled", "1")
'Enable Licensing
xParms.Add("DaemonIP", "")
'Daemon IP
xParms.Add("DaemonPort", "")
'Daemon Port
xParms.Add("DaemonUser", "")
'Daemon User
xParms.Add("DaemonPass", "")
'Daemon Password
xParms.Add("SecurityValue", SecurityRandom.ToString())
'Security Offset if enabled, or 0
xParms.Add("WorkDir", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\Nalpeiron")
'Work Directory
'Create the XML doc to pass parameters
Dim xmlParms As String = ConstructXMLVariableTag(xParms, "SHAFERXMLParams")
'Initialise NSA and record Application Start
' Convert string to byte array for Unicode compatibility
Dim UTFxmlParms() As Byte = Encoding.UTF8.GetBytes(If(xmlParms = Nothing, "", xmlParms))
Try
ShaferError = NalpLibOpen(UTFxmlParms)
If (ShaferError < 0) Then
Return ShaferError
End If
Catch e As System.BadImageFormatException
BadImage = True
Return ShaferError
End Try
'Validate the DLL (Check to see if correct DLL for This Customer and Product)
ShaferError = NSAValidateLibrary(CustomerID, ProductID)
If ShaferError < 0 Then
Return ShaferError
End If
Return ShaferError
End Function
The BadImage flag is returned as true if an x64 ShaferFileChck DLL is loaded into an x86 application or vice versa, otherwise false. The actual build platform of the application is returned by the GetBuildPlatform function:
C# Example - GetBuildPlatform
Private Function GetBuildPlatform() As String
Dim result As String = ""
If IntPtr.Size = 8 Then
result = "x64"
Else
result = "x86"
End If
Return result
End Function
VB Example - GetBuildPlatform
private string GetBuildPlatform()
{
string result = "";
if (IntPtr.Size == 8)
{
result = "x64";
}
else
{
result = "x86";
}
return result;
}
The ShowError function performs the frequently-needed task of obtaining the error message from the error code passed in. There is a second, Boolean parameter passed to this function whose purpose is to specify whether or not the application should exit.
C# Example - ShowError
//Takes the error message id and retrieves the apropriate error message to present to the user
public static void ShowError(int shaferError, bool exitApplication)
{
string errMess = "";
Shafer.GetErrorMessage(shaferError, ref errMess);
MessageBox.Show(errMess);
if (exitApplication)
{
Application.Exit();
}
}
VB Example - ShowError
'Takes the error message id and retrieves the apropriate error message to present to the user
Protected Shared Sub ShowError(errorId As Int32, Optional exitApplication As Boolean = True)
Dim ErrMess = ""
Shafer.GetErrorMessage(errorId, ErrMess)
MessageBox.Show(ErrMess)
If exitApplication Then
Application.[Exit]()
End If
End Sub
3. Retrieve and Check the License Status
C# Example - GetLicenseStatus
//Get License Status
ShaferError = oShafer.GetLicenseStatus(ref LicenseStatus);
if (ShaferError != 0)
{
ShowError(ShaferError);
}
VB Example - GetLicenseStatus
'Get License Status
ShaferError = oShafer.GetLicenseStatus(LicenseStatus)
If ShaferError <> 0 Then
ShowError(ShaferError)
End If
4. Additional Security Checks
Add the security code to check the license status: if the license status shows that the client computer has been backdated then show a message and exit application. This will give the user the prompt to correct their computer's date and time before running the application again:
C# Example - Security Check
//SECURITY: If computer has been BACK Dated to get more time for the trial or Subscription then Exit Application
if (LicenseStatus == (int) Shafer.LicenseStatus.PROD_BTCOUNTER)
{
ShowError(ShaferError);
}
VB Example - Security Check
'SECURITY: If computer has been BACK Dated to get more time for the trial or Subscription then Exit Application
If LicenseStatus = CInt(Shafer.LicenseStatus.PROD_BTCOUNTER) Then
ShowError(ShaferError)
End If
5. Retrieve License from Server
Add the following code to check the license status: if a positive value is returned then the license status is good for your application to continue running. It will be in either trial or activated (with a license code) mode.
If the value is negative or 0 then the client will need to attempt to get a refreshed license from the activation server via the function GetLicenseFromServer(), which defined and explained in Step 7.)
C# Example - Get License from Server
//If License Status is negative then try to get license from server, if not then prompt for manual activation
if (LicenseStatus <= 0)
{
LicenseStatus = GetLicenseFromServer(false);
}
else
{
// Extra security procedure: if license table overwritten on an online system, the license table will refresh itself.
// Don't try License Refresh if Network LTCO - daemon doesn't allow LTCO Refreshes for security reasons
if (LicenseStatus != (int)Shafer.LicenseStatus.PROD_NETWORK_LTCO)
{
// To enable the license to be refreshed (update local entitlements from the server) on application start, we need to attempt a license refresh. If offline then continue running with the local entitlements. If online then refresh from the server.
LicenseStatus = GetLicenseFromServer(true);
}
}
VB Example - Get License from Server
'If License Status is negative then try to get license from server, if not then prompt for manual activation
If LicenseStatus <= 0 Then
LicenseStatus = GetLicenseFromServer(False)
Else
'Extra security procedure: If License Then table overwritten On an online system, the license table will refresh itself.
'Don't try License Refresh if Network LTCO, Daemon doen't allow LTCO Refesh's for security reasons
If LicenseStatus <> (Int(Shafer.LicenseStatus.PROD_NETWORK_LTCO)) Then
'To enable the license to be refreshed (update local entitlements from the server) on application start, we need to attempt a license refresh. If offline then continue running with the local entitements. If online then refresh from the server.
LicenseStatus = GetLicenseFromServer(True)
End If
End If
6. Get the License Information
There are two kinds of license information which determine the kind of license being used:
- License Type: e.g. whether the license is trial or activation (with a license code), subscription or perpetual, node-locked or concurrent.
- Activation Type: e.g. whether the license was activated on or offline.
The GetLicenseInfo function obtains this information and is wrapped in method ShowLicenseStatus which can be found following the calls to GetLicenseFromServer in your form Load event. The code for GetLicenseInfo is as follows:
C# Example - Get License Info
private void GetLicenseInfo(ref string licensetype, ref string activationtype)
{
UInt32 ltype = 0;
UInt32 atype = 0;
ShaferError = oShafer.GetLicenseInfo(ref ltype, ref atype);
if (ShaferError == 0)
{
licensetype = Shafer.GetLicenseType(ltype);
activationtype = Shafer.GetActivationType(atype);
}
else
{
ShowError(ShaferError, true);
}
}
VB Example - Get License Info
Private Sub GetLicenseInfo(ByRef licensetype As String, ByRef activationtype As String)
Dim ltype As UInt32
Dim atype As UInt32
ltype = 0
atype = 0
ShaferError = oShafer.GetLicenseInfo(ltype, atype)
If ShaferError = 0 Then
licensetype = Shafer.GetLicenseType(ltype)
activationtype = Shafer.GetActivationType(atype)
Else
ShowError(ShaferError, True)
End If
End Sub
7. Setup your application to check the license status at regular intervals whilst running
This step is required so your running application will check with the application server to refresh its local license from the activation server at regular intervals while it is running.The local Client License is only valid for the set Client Lease period for the trial or for the activated License code.When the client Lease has expired the client is required to retrieve a new license from the server.This allows the client to expire (subscription or trial) during the execution of the application, instead of just at application start At the end of the VBShaferExample_Load(object sender, EventArgs e) event handler, when a connection to Zentitle has been established and the licensing is verified as operational, insert a call to StartTimer() where this function is given by the following: At the end of the ShaferExample_Load(object sender, EventArgs e) event handler, when a connection to Zentitle has been established and the licensing is verified as operational, insert a call to StartTimer() where this function is given by the following:
C# Example - Start Timer
public void StartTimer()
{
timer.Tick += new EventHandler(timer_Tick); // Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000) * (120); // Timer will tick evert 2 mins
timer.Enabled = true; // Enable the timer
timer.Start();
}
VB Example - Start Timer
Public Sub StartTimer()
AddHandler timer.Tick, AddressOf timer_Tick
' timer.Tick += New EventHandler(timer_Tick)
' Everytime timer ticks, timer_Tick will be called
timer.Interval = (1000) * (120)
' Timer will tick evert 2 mins
timer.Enabled = True
' Enable the timer
' Start the timer
timer.Start()
End Sub
Then add the timer handler to call the following code, to check the License status and retrieve new license is required.
C# Example - Timer tick event
private void timer_Tick(object sender, EventArgs e)
{
var LicenseStatus = 0;
//Get License Status
ShaferError = oShafer.GetLicenseStatus(ref LicenseStatus);
if ((ShaferError != 0) && (ShaferError != -1094)) //No license
{
ShowError(ShaferError);
}
//SECURITY: If computer has been BACK Dated to get more time for the trial or Subscription then Exit Application
if (LicenseStatus == (int) Shafer.LicenseStatus.PROD_BTCOUNTER)
{
ShowError(ShaferError);
}
//If License Status is negative then try to get license from server
if (LicenseStatus <= 0)
GetLicenseFromServer(false);
// ShowLicenseStatus(LicenseStatus);
}
VB Example - Timer tick event
Private Sub timer_Tick(sender As Object, e As EventArgs)
Dim LicenseStatus = 0
'Get License Status
ShaferError = oShafer.GetLicenseStatus(LicenseStatus)
If ShaferError <> 0 AndAlso ShaferError <> -1094 Then 'No license
ShowError(ShaferError)
End If
'SECURITY: If computer has been BACK Dated to get more time for the trial or Subscription then Exit Application
If LicenseStatus = CInt(Shafer.LicenseStatus.PROD_BTCOUNTER) Then
ShowError(ShaferError)
End If
'If License Stauts is negative then try to get license form server
If LicenseStatus <= 0 Then
GetLicenseFromServer(False)
End If
ShowLicenseStatus(LicenseStatus)
End Sub
Code Integration Walkthrough - Analytics
The following code examples are required for generating analytics data.
ApplicationStart Logging
Add code at the bottom of your Load event to call method ApplicationStart which you can find in the Shafer.cs class. This method takes the following parameters:
| Parameters | Description |
|---|---|
| NSAUsername (string) | This is the recorded username of user starting the application, if not required or available set to empty string. |
| Applanguage (string) | Set to the ISO 2 digit language code for the application's running Language. |
| Version (String) | Set to your application's Major version number. |
| Build (String) | Set to your application's Build Number. |
| Edition (String) | Set to your application's Edition. |
| LicenseStatus (String) | Set to your application's License Status. If using NSL use return value from GetLicenseStatus as shown below |
C# Example - Application Start
System.Reflection.Assembly thisAssembly = this.GetType().Assembly;
CultureInfo ci = CultureInfo.InstalledUICulture;
//Check the privacy settings if required
ShaferError = oShafer.GetPrivacy();
if (ShaferError < 0)
{
ShowError(ShaferError, true);
}
else if ((Shafer.PrivacyValues)ShaferError == Shafer.PrivacyValues.NOT_SET)
{
//If privacy not set then prompt and set
DialogResult dialogResult = MessageBox.Show("You are not currently participating in our product improvement program, participate in the direction of future versions of our products by clicking Yes, below"
, "Privacy", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
//Set to allow data transmission
ShaferError = oShafer.SetPrivacy(Shafer.PrivacyValues.OFF);
}
else
{
//Set to disallow data transmission
ShaferError = oShafer.SetPrivacy(Shafer.PrivacyValues.ON);
}
if (ShaferError < 0)
{
ShowError(ShaferError, true);
}
}
//If privacy already set then don't ask again
//Record the application Start
ShaferError = oShafer.ApplicationStart(NSAUsername, ci.Name, thisAssembly.GetName().Version.Major.ToString(), "ENT", thisAssembly.GetName().Version.Minor.ToString(), LicenseStatus == (int)Shafer.LicenseStatus.PROD_INTRIAL ? "Trial" : "Activated");
if (ShaferError < 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
ShowError(ShaferError, true);
}
else
{
AppStarted = true;
}
VB Example - Application Start
Dim thisAssembly As System.Reflection.Assembly = Me.[GetType]().Assembly
Dim ci As CultureInfo = CultureInfo.InstalledUICulture
'Check the privacy settings if required
ShaferError = oShafer.GetPrivacy()
If ShaferError < 0 Then
ShowError(ShaferError, True)
ElseIf CType(ShaferError, Shafer.PrivacyValues) = Shafer.PrivacyValues.NOT_SET Then
'If privacy not set then prompt and set
Dim dialogResult__1 As DialogResult = MessageBox.Show("You are not currently participating in our product improvement program, participate in the direction of future versions of our products by clicking Yes, below", "Privacy", MessageBoxButtons.YesNo)
If dialogResult__1 = DialogResult.Yes Then
'Set to allow data transmission
ShaferError = oShafer.SetPrivacy(Shafer.PrivacyValues.OFF)
Else
'Set to disallow data transmission
ShaferError = oShafer.SetPrivacy(Shafer.PrivacyValues.ON)
End If
If ShaferError < 0 Then
ShowError(ShaferError, True)
End If
End If
If txtNSAUsername.Text = "" Then
txtNSAUsername.Text = "Username"
End If
'Record the application Start
ShaferError = oShafer.ApplicationStart(NSAUsername, ci.Name, thisAssembly.GetName().Version.Major.ToString(), "ENT", thisAssembly.GetName().Version.Minor.ToString(), If(LicenseStatus = CInt(Shafer.LicenseStatus.PROD_INTRIAL), "Trial", "Activated"))
If ShaferError < 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
ShowError(ShaferError, False)
Else
AppStarted = True
End If
ApplicationEnd Cleanup
When your application ends the following cleanup tasks must be carried out:
- For a cloud or network concurrent license, the license must be returned.
- Any floating feature seats must be returned.
The following example shows the code to return a concurrent license on trapping of the form close event. Code for returning a floating feature seat is shown further below.
C# Example - Application End
private void ShaferExample_FormClosing(object sender, FormClosingEventArgs e)
{
if (!JustExit)
{
int LicenseStatus = 0;
bool Concurrent = false;
string licensetype = "";
string activationtype = "";
GetLicenseInfo(ref licensetype, ref activationtype);
if (new List { "Permanent (concurrent)", "Subscription (concurrent)", "Network License" }.Contains(licensetype))
{
Concurrent = true;
}
//ON Exit Check to see If concurrency License if so then return the license to the server to acheive concurrency
ShaferError = oShafer.GetLicenseStatus(ref LicenseStatus);
if (ShaferError < 0)
{
ShowError(ShaferError, true);
}
if (LicenseStatus > 0 && Concurrent == true)
{
//Return the license to the server to free up the activation for another client
string LicenseCode = GetLicenseCode();
if (LicenseCode == "")
{
MessageBox.Show("Licensecode is required to return the license");
}
ShaferError = oShafer.ReturnLicense(LicenseCode);
if (ShaferError < 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
ShowError(ShaferError, false);
}
}
ShaferError = oShafer.ApplicationEnd(NSAUsername);
if (ShaferError < 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
ShowError(ShaferError, false);
}
}
else
{
Environment.Exit(0);
}
}
VB Example - Application End
Private Sub ShaferExample_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If Not JustExit Then
Dim LicenseStatus As Integer = 0
Dim Concurrent As Boolean = False
Dim licensetype As String = ""
Dim activationtype As String = ""
GetLicenseInfo(licensetype, activationtype)
If (New List(Of String)({"Permanent (concurrent)", "Subscription (concurrent)"}).Contains(licensetype)) Then
Concurrent = True
End If
'ON Exit Check to see If concurrency License if so then return the license to the server to acheive concurrency
ShaferError = oShafer.GetLicenseStatus(LicenseStatus)
If ShaferError < 0 Then
ShowError(ShaferError, False)
End If
If LicenseStatus > 0 And Concurrent = True Then
'Return the license to the server to free up the activation for another client
Dim LicenseCode As String = GetLicenseCode()
If LicenseCode = "" Then
MessageBox.Show("Licensecode is required to return the license")
End If
ShaferError = oShafer.ReturnLicense(LicenseCode)
If ShaferError < 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
ShowError(ShaferError, False)
End If
End If
If (AppStarted = True) Then
ShaferError = oShafer.ApplicationEnd(NSAUsername)
If ShaferError < 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
ShowError(ShaferError, False)
End If
End If
Else
Environment.Exit(0)
End If
End Sub
Exception Logging
Add code to call method Exception which you can find in the Shafer.cs class. This method takes the following parameters:
| Function | Parameters | Description |
|---|---|---|
| Exception | NSAUsername (String) | This is the recorded username of user running the application, if not required or available set to empty string. |
| ExceptionCode (string) | This is the errorcode of the exception thrown. | |
| Description (String) | This is the description of the error thrown. |
C# Example - Exception Logging
private void ThrowError_Click(object sender, EventArgs e)
{
try
{
throw new System.ArgumentException("NSA Example Exeception", "NSA Example Application");
}
catch (Exception ex)
{
ShaferError = oShafer.Exception(Username, System.Runtime.InteropServices.Marshal.GetExceptionCode().ToString(), ex.Message.ToString());
if (ShaferError != 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
}
}
VB Example - Exception Logging
Private Sub ThrowError_Click(sender As Object, e As EventArgs) Handles ThrowError.Click
Try
Throw New System.ArgumentException("NSA Example Exeception", "NSA Example Application")
Catch ex As Exception
ShaferError = oShafer.Exception(NSAUsername, System.Runtime.InteropServices.Marshal.GetExceptionCode().ToString(), ex.Message.ToString())
If ShaferError <> 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
End If
End Try
End Sub
Feature Use Logging
Add code to call the following functions which you can find in the Shafer.cs class to each feature in your application you would like to be recorded.
| Function | Parameters | Description |
|---|---|---|
| GetFeatureStatus | FeatureCode (String) | The feature code setup on the NSA server to check for availability. |
| TxnID (Uint32) | Set to 0 | |
| FeatureStart | NSAUsername (String) | This is the recorded username of user running the application, if not required or available set to empty string. |
| FeatureCode (String) | The feature code setup on the NSA server which records the required feature usage. | |
| TxnID (ref Uint32) | Returned is the Transaction ID specific for this FeatureStart and must be passed to the corresponding FeatureEnd | |
| FeatureEnd | NSAUsername (String) | This is the recorded username of user running the application, if not required or available set to empty string. |
| FeatureCode (String) | The feature code setup on the NSA server which records the required feature usage. | |
| TxnID (Uint32) | The Transaction ID returned from the associated FeatureStart |
- If you just need to record a feature being triggered use FeatureStart, without FeatureEnd
- If you need to be able to calculate how long a feature has ran for use FeatureStart AND FeatureEnd together as in the example shown
- Use CheckoutFloatingFeature/CheckinFloatingFeature to check out/in floating feature seats.
C# Example - Feature Logging
private void feature1ToolStripMenuItem_Click(object sender, EventArgs e)
{
int FeatureStatus = 0;
UInt32 TxnID = 0;
ShaferError = oShafer.GetFeatureStatus("FEAT1", ref FeatureStatus, 0);
if (ShaferError != 0 && FeatureStatus != -4)
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
if (FeatureStatus != 1)
{
MessageBox.Show("Function not activated");
return;
}
ShaferError = oShafer.FeatureStart(NSAUsername, "FEAT1", ref TxnID);
if (ShaferError != 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
//DO Function Code
ShaferError = oShafer.FeatureEnd(NSAUsername, "FEAT1", TxnID);
if (ShaferError != 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
}
Private Sub feature2ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles feature2ToolStripMenuItem.Click
Dim FeatureStatus As Integer = 0
Dim TxnID As UInt32 = 0
'Get the license code for the Feature Checkout/Checkin
Dim LicenseCode As String = GetLicenseCode()
ShaferError = oShafer.CheckoutFloatingFeature(LicenseCode, "FEAT2", FeatureStatus)
If ShaferError <> 0 Then
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
Return
End If
If FeatureStatus <> 1 Then
Select Case FeatureStatus
Case CInt(Shafer.FEATSTATUS.FEATSTATUS_DENIED)
MessageBox.Show("No seats available")
Return
Case Else
MessageBox.Show("Function not activated")
Return
End Select
End If
ShaferError = oShafer.FeatureStart(NSAUsername, "FEAT2", TxnID)
If ShaferError <> 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
Return
End If
MessageBox.Show("Feature2Running")
'Waste some time
ShaferError = oShafer.CheckinFloatingFeature(LicenseCode, "FEAT2")
If ShaferError <> 0 Then
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
End If
ShaferError = oShafer.FeatureEnd(NSAUsername, "FEAT2", TxnID)
If ShaferError <> 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
End If
End Sub
User Logging
Add code to call the following functions located in the Shafer.cs class in your code recording a user logon and logoff.
| Function | Parameters | Description |
|---|---|---|
| LogUserOn | NSAUsername (String) | This is the recorded username of the user logging on. |
| TxnID (Uint32) | Returned is the Transaction ID specific for this LogUserOn and must be passed to the corresponding LogUserOff | |
| LogUserOff | NSAUsername (String) | This is the recorded username of the user logging off. |
| TxnID (Uint32) | The Transaction ID returned from the associated LogUserOn |
C# Example - User Logging
private void btnLogon_Click(object sender, EventArgs e)
{
ShaferError = oShafer.LogUserOn(NSAUsername, ref UserLoginTxnID);
if (ShaferError != 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
}
private void btnLogoff_Click(object sender, EventArgs e)
{
ShaferError = oShafer.LogUserOff(NSAUsername, UserLoginTxnID);
if (ShaferError != 0 && ShaferError != -1079 && ShaferError != -1080) // Forbidden by privacy setting
{
string ErrMess = "";
Shafer.GetErrorMessage(ShaferError, ref ErrMess);
MessageBox.Show(ErrMess);
}
}
VB Example - User Logging
Private Sub btnLogon_Click(sender As Object, e As EventArgs) Handles btnLogon.Click
ShaferError = oShafer.LogUserOn(NSAUsername, UserLoginTxnID)
If ShaferError <> 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
End If
End Sub
Private Sub btnLogoff_Click(sender As Object, e As EventArgs) Handles btnLogoff.Click
ShaferError = oShafer.LogUserOff(NSAUsername, UserLoginTxnID)
If ShaferError <> 0 AndAlso ShaferError <> -1079 AndAlso ShaferError <> -1080 Then ' Forbidden by privacy setting
Dim ErrMess As String = ""
Shafer.GetErrorMessage(ShaferError, ErrMess)
MessageBox.Show(ErrMess)
End If
End Sub
Build, Run and Test your Application

Ensure that the ShaferFilechck.dll library and license code (stored in license.txt) are in the same folder as your application's executable and then move on to the next step. In Visual Studio, this will, by default, be either the /bin/release or /bin/debug folder depending on whether your build configuration is or debug or release. You have now seen how Zentitle licensing works within a demo application. The next step is to examine the licensing logic of this application in more depth so that you will have a greater understanding of how to implement it within your own application.
Download the Example Applications attached
Release Notes (Please always check the release notes for the latest updates)
Note: you need to be using the latest DLL to use these examples, if you are using older DLLs you may need older example code from Support.