PLUSManagedBackground Checking and Refreshing Licenses

Checking the status of an activated license by calling SOLO Server web services is an effective and efficient way to validate if activated licenses should remain authorized. These checks can prevent copies of your application from running in scenarios like the following:

In each case, the background check will verify the system on which the application was activated is still authorized by verifying the status of the license and the individual system's activation are still valid.  If the background check indicates the license is no longer authorized for the activated system, then your application can take steps needed to disable itself as needed. This is especially important to securely enforce deactivations.

Important

Be mindful about whether or not disabling access to your application is appropriate.  For example, if your application requires high availability (such as a web application or service) and/or your application serves some mission-critical function, it may be more appropriate to have your application display nag messages and/or disable only non-critical features so as to avoid disrupting your customers' business or operation.

Important

When using background checking or license refreshing features, it is very important that you test this functionality in your application while running in an environment where connections are refused or unavailable, and also where connections time out. Doing so can help you identify areas of your application that may become unresponsive or unstable when your application encounters these conditions.

Background Checking Licenses

The XML Activation Service web service has a CheckInstallationStatus method, which your application can leverage to check the status of the license and the status of the system's activation. This is particularly ideal when your application needs to check its status frequently (such as every time the application runs, or every time a critical feature of your application is used if it is always running).

C#
public override bool CheckInstallationStatus()
{
//initialize the object used for calling the web service method
using (XmlActivationService ws = new XmlActivationService())
{
if (!base.CheckInstallationStatus(ws))
{
if (LastError.ExtendedErrorNumber == 5010 ||
LastError.ExtendedErrorNumber == 5015 ||
LastError.ExtendedErrorNumber == 5016 ||
LastError.ExtendedErrorNumber == 5017)
{
File.Delete("[License File Path]");
}
return false;
}
}

return true;
}
VB.NET
Public Overrides Function CheckInstallationStatus() As Boolean
'initialize the object used for calling the web service method
Using ws As New XmlActivationService()
If Not MyBase.CheckInstallationStatus(ws) Then
If LastError.ExtendedErrorNumber = 5010 Or
LastError.ExtendedErrorNumber = 5015 Or
LastError.ExtendedErrorNumber = 5016 Or
LastError.ExtendedErrorNumber = 5017 Then
File.Delete("[License File Path]")
End If
Return False
End If
End Using

Return True
End Function

Note how this example code deletes the license when SOLO Server returns certain result codes. This is because the license should be considered invalid when the application receives one of these result codes from SOLO Server. Deleting the license file is an appropriate response to these result codes for read-only License implementations.  However, when using WritableLicense implementations, you should alter the local license file in-code as appropriate for your licensing requirements, and save it and its aliases.

Refreshing Licenses

You may also implement license refreshing in your application. This allows your application to query SOLO Server for a license file with the latest licensing data, while also performing a background status check. This is ideal for validating licenses with SOLO Server and updating license data periodically and/or on demand.

Determine if a License Refresh is Due

Refreshing the license file requires much more server and application resources, so it is important to avoid using this feature too frequently in your protected applications.

All of the Protection PLUS 5 SDK samples include settings or properties which you may reference and re-configure as needed for your application. For more flexibility, we recommend using the License Validation Options in SOLO Server, as this allows you to configure the refresh frequency values at the Product Option or License level instead of hard-coding them into your application. You can then easily adjust the frequency of when a license refresh is due without having to update your source code and deploy a new build.

The available License Validation Options are:

These values will be added to the license file if the License in SOLO Server is configured with License Validation Options. The license file also contains a SignatureDate property, which tells you when the license file was last issued by SOLO Server. This date field, along with the License Validation Options data allows you to implement logic to only validate with SOLO Server after a certain amount of time has passed:

C#
private bool IsRefreshLicenseAttemptDue
{
get
{
//Calculate the date difference between license signature date and the current date
TimeSpan dateDiff = DateTime.UtcNow.Subtract(m_License.SignatureDate);

if (m_License.LicenseValidationOptions.RefreshLicenseAlwaysRequired ||
(m_License.LicenseValidationOptions.RefreshLicenseAttemptFrequency > 0 &&
(dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseAttemptFrequency ||
(m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency > 0 && dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency))))
{
//license refresh is due
return true;
}
return false;
}
}
C#
private bool IsRefreshLicenseRequired
{
get
{
//Calculate the date difference between signature date and the current date
TimeSpan dateDiff = DateTime.UtcNow.Subtract(m_License.SignatureDate);

if (m_License.LicenseValidationOptions.RefreshLicenseAlwaysRequired ||
(m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency > 0 && dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency))
{
return true;
}
return false;
}
}
VB.NET
Private ReadOnly Property IsRefreshLicenseAttemptDue() As Boolean
Get
'Calculate the date difference between signature date and the current date
Dim dateDiff As TimeSpan = DateTime.UtcNow.Subtract(m_License.SignatureDate)
If (m_License.LicenseValidationOptions.RefreshLicenseAlwaysRequired OrElse
(m_License.LicenseValidationOptions.RefreshLicenseAttemptFrequency > 0 AndAlso
(dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseAttemptFrequency OrElse
(m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency > 0 AndAlso dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency)))) Then
Return True
End If
Return False
End Get
End Property

VB.NET
Private ReadOnly Property IsRefreshLicenseRequired() As Boolean
Get
'Calculate the date difference between signature date and the current date
Dim dateDiff As TimeSpan = DateTime.UtcNow.Subtract(m_License.SignatureDate)
If (m_License.LicenseValidationOptions.RefreshLicenseAlwaysRequired Or
(m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency > 0 And dateDiff.TotalDays > m_License.LicenseValidationOptions.RefreshLicenseRequireFrequency)) Then
Return True
End If
Return False
End Get
End Property

Refresh the License

When Refreshing a license, it will overwrite the existing local license file, which will have an updated SignatureDate as well as any other updated license data from SOLO Server:

C#
public bool RefreshLicense()
{
string lfContent = "";
//initialize the object used for calling the web service method
using (XmlLicenseFileService ws = new XmlLicenseFileService())
{
if (!base.RefreshLicense(ws, ref lfContent))
{
if (LastError.ExtendedErrorNumber == 5010 ||
LastError.ExtendedErrorNumber == 5015 ||
LastError.ExtendedErrorNumber == 5016 ||
LastError.ExtendedErrorNumber == 5017)
{
File.Delete("[License File Path]");
}
return false;
}
}

//try to save the license file to the file system
try
{
File.WriteAllText("[License File Path]", lfContent);
}
catch (Exception ex)
{
this.LastError = new LicenseError(LicenseError.ERROR_COULD_NOT_SAVE_LICENSE, ex);
return false;
}

return true;
}
VB.NET
Public Overloads Function RefreshLicense() As Boolean
Dim lfContent As String = ""
'initialize the object used for calling the web service method
Using ws As New XmlLicenseFileService()
If Not Me.RefreshLicense(ws, lfContent) Then
If Me.LastError.ExtendedErrorNumber = 5010 Or _
Me.LastError.ExtendedErrorNumber = 5015 Or _
Me.LastError.ExtendedErrorNumber = 5016 Or _
Me.LastError.ExtendedErrorNumber = 5017 Then
File.Delete("[LicenseFile Path")
End If
Return False
End If
End Using

'try to save the license file to the file system
Try
File.WriteAllText("[License File Path]", lfContent)
Catch ex As Exception
Me.LastError = New LicenseError(LicenseError.ERROR_COULD_NOT_SAVE_LICENSE, ex)
Return False
End Try

Return True
End Function

Note how this example code deletes the license when SOLO Server returns certain result codes. This is because the license should be considered invalid when the application receives one of these result codes from SOLO Server. Deleting the license file is an appropriate response to these result codes for read-only License implementations.  However, when using WritableLicense implementations, you should alter the local license file in-code as appropriate for your licensing requirements, and save it and its aliases.

Important

Be mindful about whether or not disabling access to your application is appropriate.  For example, if your application requires high availability (such as a web application or service) and/or your application serves some mission-critical function, it may be more appropriate to have your application display nag messages and/or disable only non-critical features so as to avoid disrupting your customers' business or operation.

Manually Refreshing a License

There may be cases where a user does not have direct access to the Internet, yet there is a requirement to allow license refreshing. In these cases, a manual refresh can be performed. To perform a refresh without the PLUSManagedGui component, it’s nearly identical to doing manual activations, except you’ll use GetLicenseRefreshRequest to generate the request data the user will copy to a system with Internet access, then use ProcessLicenseRefreshResponse to process the response data.