Learn how to implement offline software license validation with LicenseSpring's step-by-step guide. Ensure seamless license validation even without an internet connection.
How to Add Software License Validation to a C++ Application [Tutorial]
In this tutorial, we will go through the step-by-step process of activating your LicenseSpring license using the LicenseSpring C++ SDK.
This basic tutorial will help you understand how to use the LicenseSpring C++ SDK and how it can be integrated into your product. By the end of this tutorial, you should be able to activate, deactivate and check your license from your C++ program. For this tutorial, we will create a Chatbot that can activate, deactivate, and check a LicenseSpring license. This tutorial will not acknowledge offline activation, deactivation or checks. The article that covers these topics can be found in our tutorial on working with offline software license activation, deactivation and local license checks.
Licenses can be activated and deactivated using the Chatbot, as shown below:
Sections:
- Prerequisites
- Setting Up a License
- Acquiring the SDK
- Setting Up Folder Hierarchy
- Initializing the SDK
- Creating the Chatbot
- Static and Dynamic Linking
- Common Problems
Prerequisites:
We will be using C++ in Visual Studio Community Edition 2022 on Windows for this tutorial.
- Download Visual Studio Community Edition 2022
- Make sure Desktop Development with C++ and the Windows SDK for the version being used are downloaded on your Visual Studio. These can be downloaded alongside Visual Studio within Visual Studio Installer. If you have previously installed Visual Studio, you can add these by selecting modify and checking the boxes inside Visual Studio Installer.
Desktop Development with C++:
Visual Studio Windows SDK:
Setting Up a License:
To set up a license, please follow the steps on the getting started page. For this tutorial, we will be using a perpetual license. In other tutorials, we will go through consumption, subscription and time-based licenses.
Getting the SDK:
The C++ SDK can be found at: C++ - Documentation. For this tutorial we will download the VC143 SDK, created for the 2022 version of Visual Studio.
Make sure to download the SDK that fits your current Visual Studio version. Downloading the wrong version may have deprecated functions or have functions that may not function as intended. Generally, older versions of the SDK will work on newer versions of Visual Studio, but newer SDK versions may have functions that will not work on older versions of Visual Studio.
Setting Up Folder Hierarchy:
After unzipping the SDK, you will have this folder structure:
For this tutorial, we will be placing our chatbot.cpp in the CppSample folder. Note: You can set up your folder structure differently, but make sure you adjust the path names on your headers and other path related lines of code.
Initializing the SDK:
To initialize the SDK, at the top of chatbot.cpp, you will need to fill in your name of application, version of application, LicenseSpring API key, LicenseSpring Shared key, product code and license key (or user email and password).
The values of name and version are customizable and should be set to appropriately represent your application.
Your LicenseSpring API key and Shared key can be found on your LicenseSpring account under Settings>Keys.
Your product code is located in your product list under Configure Products.
If you are using a user-based license, you should comment out the key-based license code and uncomment the user-based license code, as shown below.
1
2
3
4
5
6
7
//Key-based implementation
//auto licenseId = LicenseID::fromKey("XXXX-XXXX-XXXX-XXXX"); //input license key
//For user-based implementation comment out above line, and use bottom 3 lines
const std::string userId = "example@email.com"; //input user email
const std::string userPassword = "testpassword"; //input user password
auto licenseId = LicenseID::fromUser( userId, userPassword );
Your key, or the email and password of users, can be found on the licenses page. Utilizing a user-based license requires users to be created and assigned to the license. This is done by entering the user-based license, switching to the users tab, and clicking “assign license user”.
Creating the Chatbot:
We wrote a sample chatbot that can be found on Github here.
We find the local license with the following method:
1
auto license = licenseManager->getCurrentLicense();
The local license is a copy of the license information that is saved on the end user's local computer. Users who have not activated the license on their end before will not have a local license, and this will return null. However, if the license is not null, this does not necessarily mean that the license is activated on the backend (it could just be deleted locally). By default, the local license is stored: %USERPROFILE%\AppData\Local\LicenseSpring\”Product Code”\License.key.
The process of activating a license refers to binding a device to a license. On the LicenseSpring platform, activating the license increments the total activations counter within the license. Within the chatbot, we use the following to activate the license online:
1
license = licenseManager->activateLicense( licenseId );
Deactivating a license unbinds the device from the license, and decrements the number of total activations. Depending on the license transfer policy, this usually means that the license is freed up to be activated onto a new device. Deactivating is done in the chatbot through using the following method to communicate to the backend that the connection is ending:
1
license->deactivate( true );
In the chatbot, to run an online and local check of the license we call:
1
LicenseCheck( license );
Within this function, to check the online status of the license we use:
1
license->check();
License Check refreshes the local license file with the latest entitlements that are stored on the LicenseSpring servers, and can throw exceptions to describe the problem that occurred in the event an exception is thrown.
To check the license local to the device without connecting to the backend we use:
1
license->localCheck();
This localcheck() function also throws exceptions describing what went wrong. This can be very useful to check if a license is still valid, and/or underwent license tampering. It will throw an exception if it catches any of these cases. The best practice is to perform a localCheck (offline check) on every startup to be sure that the license file wasn’t copied from another computer, and that the license is in a valid state.
Note on License Statuses: In LicenseSpring, an active license does not necessarily mean a license is valid. A valid license means the license is active, enabled, and not expired. An active license means that the license is bound to a device, but may also be disabled or expired.
You can also check for valid, enabled, and expired licenses the same way you would check for active licenses using isValid(), isEnabled(), and isExpired() respectively. For this tutorial, we will stick with isActive(), since we only care about activating, deactivating, and checking a license.
Static and Dynamic Linking:
Brief Description:
- Static linking is the process of copying all library modules used in the program into the final executable image.
- In dynamic linking the names of the external libraries are placed in the final executable file while the actual linking takes place at run time.
Size of File:
- Statically linked files are significantly larger in size because external programs are built into the executable files.
- In dynamic linking only one copy is kept in memory, significantly reducing the size of executable programs
Load Time:
- Statically linked program takes constant load time every time it is loaded into the memory for execution.
- In dynamic linking load time might be reduced if the shared library code is already present in memory.
Execute Time:
- Programs that use statically-linked libraries are usually faster than those that use shared libraries.
- Programs that use shared libraries are usually slower than those that use statically-linked libraries.
Compatibility:
- In static, all code is contained in a single executable module. Therefore, they never run into compatibility issues.
- Dynamically linked programs are dependent on having a compatible library. If a library is changed, applications might have to be reworked to be made compatible with the new version of the library.
You can find more information regarding static and dynamic linking differences here [external link].
You can switch between static linking (/MT) or dynamic linking (/MD) using our tutorial sample code. Note in the LicenseSpring/bin folder, for both x64 and x86, there is a dynamic, staticMD and staticMT folder. To switch between /MT and /MD, you can manually update them using the Visual Studio IDE. In your upper tab go to Project>Properties>Configuration Properties>C/C++>Code Generation. Then, next to the Runtime Library, select the type of linking you want to use, then press apply.
Then, in your upper tab, make sure your runtime setting matches the one you just chose in project settings.
Finally, if you have more than one project, right-click the project you want to run, and select Set as Startup Project.
Common Problems:
Error: No such file/directory error on include statements referencing LicenseSpring files.
- Double-check that your folder hierarchy is consistent with the image provided above (link image title or name)
LicenseSpring exception encountered: apiKey could not be empty
- apiKey can be found in LicenseSpring>Settings>Keys then under API Key (UUID). This key must be provided for the create function to execute.
LicenseNoAvailableActivationsException: The license has reached its maximum allotted activations.
- Either deactivate a license to allow a new addition, or increase the maximum number of activations by clicking the “Edit License” button on the respective license page.
NetworkTimeoutException: A network timeout occurred during the activation of the license
- Resolve external network problems or activate the license utilizing the “Offline Licensing” feature.
LicenseStateException: Tried to check a disabled, inactive, or expired license.
- If the license is inactive, activate it and check again. If disabled, then enable and try to check again. If the license is expired, adjust the expiration date. You can also put the exception in a try-catch statement.