Before you can do anything, you need to login to your LimeLM account (or sign up) and download the TurboActivate.zip. This zip contains the TurboActivate.dll & TurboActivate.exe along with source code examples.
We're going to walk you through each step you need to add licensing to your Inno Setup installer. By the end of this walkthrough you'll have added a product key page to your installer that will verify & activate the product key and will also deactivate the user when they uninstall your app:
This tutorial is written for the Unicode version of Inno Setup. The way you can tell whether you have the Unicode or non-Unicode (aka Ansi) version of Inno Setup installed is by launching the Inno Setup Compiler and looking at the title bar:
The Unicode version of Inno Setup will have a little "u" in parentheses. If that "(u)" isn't present in the titlebar of the Inno Setup compiler then uninstall the Inno Setup compiler from your computer and download the Unicode version of Inno Setup and install it.
If you haven't already signed up for LimeLM then sign up now. All plans have a 30-day free trial. Or, if you're just putting your toes in the water, there's even a free plan that has no time limit and doesn't require a credit card.
After you've created your account download TurboActivate.zip and extract it anywhere. After you extract it you'll find 3 folders:
API: This folder contains all Windows source code examples. Inside this folder you'll find the "Installers\Inno Setup" folder which contains the end-result of this tutorial: the example Inno Setup installer (TurboActivate.iss).
x64: This folder contains the 64-bit version of TurboActivate. This version only runs on 64-bit versions of Windows.
x86: This folder contains the 32-bit version of TurboActivate. This version runs on all versions of Windows. You'll be using this x86 version of TurboActivate with your Inno Setup installer for this reason.
If you haven't already created a new product in LimeLM, do it now. You can change any value later, so don't worry about making a mistake.
Go to your version page in LimeLM. Download the "TurboActivate.dat" file. Include this file with all the other files you'll be including with your installer. In the example Inno Setup you'd put this TurboActivate.dat file in the same folder as the TurboActivate.iss file.
Next copy "TurboActivate.dll" from the x86 folder you extracted. Put this file in the same folder you just copied the TurboActivate.dat file to.
Now you can open your Inno Setup Script (*.iss file) in your favorite editor. Add the 2 TurboActivate files (.dat and .dll) just under the [Files] sections:
[Files]
; Install TurboActivate to {app} so we can access it at uninstall time
; Also, notice we're putting the TurboActivate files at the top of the file
; list. This is so that if you're using "SolidCompression=yes" your installer
; can still start relatively quickly.
Source: "TurboActivate.dll"; DestDir: "{app}"
Source: "TurboActivate.dat"; DestDir: "{app}"
; all other files can go below...
Now you need to set the version GUID in your installer. On your version page in LimeLM (the page where you downloaded the TurboActivate.dat file) copy the Version GUID. Then in the [Code] section of your installer add the follow constant and paste the version GUID:
[Code]
//TODO: goto the version page at LimeLM and paste this GUID here
const
VERSION_GUID = 'Paste GUID Here';
Replace the "Paste GUID Here" string with the Version GUID string your copied from your version page.
Add the TurboActivate functions you'll be using in your installer and uninstaller underneath the VERSION_GUID constant you just defined in the [Code] section:
[Code]
//TODO: goto the version page at LimeLM and paste this GUID here
const
VERSION_GUID = 'Paste GUID Here';
// functions for activation
function TA_GetHandle(versionGUID: WideString): longint;
external 'TA_GetHandle@files:TurboActivate.dll,TurboActivate.dat cdecl setuponly';
function TA_IsActivated(handle: longint): longint;
external 'TA_IsActivated@files:TurboActivate.dll,TurboActivate.dat cdecl setuponly';
function TA_CheckAndSavePKey(handle: longint; productKey: WideString; flags: UINT): longint;
external 'TA_CheckAndSavePKey@files:TurboActivate.dll,TurboActivate.dat cdecl setuponly';
function TA_Activate(handle: longint; options: cardinal): longint;
external 'TA_Activate@files:TurboActivate.dll,TurboActivate.dat cdecl setuponly';
// functions for the uninstaller
function TA_GetHandleUninstall(versionGUID: WideString): longint;
external 'TA_GetHandle@{app}\TurboActivate.dll cdecl uninstallonly';
function TA_IsActivatedUninstall(handle: longint): longint;
external 'TA_IsActivated@{app}\TurboActivate.dll cdecl uninstallonly';
function TA_Deactivate(handle: longint; erasePkey: boolean): longint;
external 'TA_Deactivate@{app}\TurboActivate.dll cdecl uninstallonly';
function TA_Cleanup(): longint;
external 'TA_Cleanup@{app}\TurboActivate.dll cdecl uninstallonly';
var
PkeyPage: TInputQueryWizardPage;
activated: Boolean;
Now you can add the product key page to your installer. In this example we're putting it directly after the "Welcome" page. So, in your "InitializeWizard
" procedure:
procedure InitializeWizard;
begin
// create the product key page
PkeyPage := CreateInputQueryPage(wpWelcome,
'Type your product key', '',
'You can find the {#SetupSetting("AppName")} product key in the email we sent you. Activation will register the product key to this computer.');
PkeyPage.Add('Product Key:', False);
end;
Now that you've added the product key entry page to your installer you need to add the code to verify the product key and activate. You can do this in your "NextButtonClick
" function. The following code checks if the user is already activated after the Welcome screen and sets the "activated" variable which you'll use a little later to skip the product key page.
When the next button is clicked on the "PkeyPage" the product key is verified and then, if it's valid, the product key is activated. Any failure will result in a message box being shown with the human-readable error (in addition to preventing the user from continuing):
function NextButtonClick(CurPage: Integer): Boolean;
var
ret: LongInt;
begin
if CurPage = wpWelcome then begin
// get the handle for your version GUID
taHandle := TA_GetHandle(VERSION_GUID);
// error handling code
if taHandle = 0 then begin
MsgBox('Failed to get the TurboActivate handle. Make sure the TurboActivate.dat file is included with your installer and you''re using the correct VersionGUID.', mbError, MB_OK);
Result := False;
exit;
end;
// after the welcome page, check if we're activated
ret := TA_IsActivated(taHandle);
if ret = TA_OK then begin
activated := true;
end;
Result := True;
end else if CurPage = PkeyPage.ID then begin
// check if the product key is valid
ret := TA_CheckAndSavePKey(taHandle, PkeyPage.Values[0], TA_SYSTEM);
if ret = TA_OK then begin
// try to activate, show a specific error if it fails
ret := TA_Activate(taHandle, 0);
case ret of
TA_E_PKEY:
MsgBox('The product key is invalid or there''s no product key.', mbError, MB_OK);
TA_E_INET:
MsgBox('Connection to the servers failed.', mbError, MB_OK);
TA_E_INUSE:
MsgBox('The product key has already been activated with the maximum number of computers.', mbError, MB_OK);
TA_E_REVOKED:
MsgBox('The product key has been revoked.', mbError, MB_OK);
TA_E_INVALID_HANDLE:
MsgBox('The handle is not valid. You must set the VersionGUID property.', mbError, MB_OK);
TA_E_COM:
MsgBox('CoInitializeEx failed. Re-enable Windows Management Instrumentation (WMI) service. Contact your system admin for more information.', mbError, MB_OK);
TA_E_ENABLE_NETWORK_ADAPTERS:
MsgBox('There are network adapters on the system that are disabled and TurboActivate couldn''t read their hardware properties (even after trying and failing to enable the adapters automatically).' + ' Enable the network adapters, re-run the function, and TurboActivate will be able to "remember" the adapters even if the adapters are disabled in the future.', mbError, MB_OK);
TA_E_EXPIRED:
MsgBox('Failed because your system date and time settings are incorrect. Fix your date and time settings, restart your computer, and try to activate again.', mbError, MB_OK);
TA_E_IN_VM:
MsgBox('Failed to activate because this instance of your program if running inside a virtual machine or hypervisor.', mbError, MB_OK);
TA_E_INVALID_ARGS:
MsgBox('The arguments passed to the function are invalid. Double check your logic.', mbError, MB_OK);
TA_E_KEY_FOR_TURBOFLOAT:
MsgBox('The product key used is for TurboFloat, not TurboActivate.', mbError, MB_OK);
TA_E_ACCOUNT_CANCELED:
MsgBox('Can''t activate because the LimeLM account is cancelled.', mbError, MB_OK);
TA_OK: // successful
begin
activated := true;
Result := True
exit;
end
else
MsgBox('Failed to activate. Error code: ' + IntToStr(ret), mbError, MB_OK);
end;
Result := False
end else begin
MsgBox('You must enter a valid product key. Error code: ' + IntToStr(ret), mbError, MB_OK);
Result := False;
end;
end else
Result := True;
end;
Note: there are lots of ways you can handle bad product keys or failure to activate. This example shows the strictest possible handling of the failures. That is, if either the product key is invalid (or missing) or the activation fails then the installer will prevent the user from continuing. This is not the best end-user experience. A better way to handle this might be to silently fail, and then let the user enter a valid product key and/or activate later when they're using your application. See Using TurboActivate to learn how to integrate TurboActivate within your application.
Here's the more user-friendly alternative of the "NextButtonClick
" function (as compared to the one above and included in TurboActivate.iss). This version will let the user continue with the installation if either the product key is invalid or the activation fails:
function NextButtonClick(CurPage: Integer): Boolean;
var
ret: LongInt;
begin
if CurPage = wpWelcome then begin
// get the handle for your version GUID
taHandle := TA_GetHandle(VERSION_GUID);
// error handling code
if taHandle = 0 then begin
MsgBox('Failed to get the TurboActivate handle. Make sure the TurboActivate.dat file is included with your installer and you''re using the correct VersionGUID.', mbError, MB_OK);
Result := False;
exit;
end;
// after the welcome page, check if we're activated
ret := TA_IsActivated(taHandle);
if ret = TA_OK then begin
activated := true;
end;
end else if CurPage = PkeyPage.ID then begin
// check if the product key is valid
ret := TA_CheckAndSavePKey(taHandle, PkeyPage.Values[0], TA_SYSTEM);
if ret = TA_OK then begin
// try to activate, show a specific error if it fails
ret := TA_Activate(taHandle, 0);
if ret = 0 then begin
activated := true;
end;
end;
end;
// let the user continue whether they're activated or not
Result := True;
end;
If the user is already activated you should skip the product key page:
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// skip the "Pkey" page if were already activated
if (PageID = PkeyPage.ID) and activated then
Result := True
else
Result := False;
end;
Lastly, when your user uninstalls your app, you should deactivate them. You can do this by calling Deactivate()
in the
CurUninstallStepChanged
procedure:
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
ret: LongInt;
begin
// Call our function just before the actual uninstall process begins
if CurUninstallStep = usUninstall then begin
// get the handle for your version GUID
taHandle := TA_GetHandleUninstall(VERSION_GUID);
// error handling code
if taHandle = 0 then begin
MsgBox('Failed to get the TurboActivate handle. Make sure the TurboActivate.dat file is included with your installer and you''re using the correct VersionGUID.', mbError, MB_OK);
end else begin // valid handle
// deactivate if activated
if TA_IsActivatedUninstall(taHandle) = TA_OK then begin
// change the second parameter to "True" if you want to
// delete the product key from the computer after your app is deactivated
ret := TA_Deactivate(taHandle, False);
end;
end;
TA_Cleanup();
// Now that we're finished with it, unload TurboActivate.dll from memory.
// We have to do this so that the uninstaller will be able to remove the DLL and the {app} directory.
UnloadDLL(ExpandConstant('{app}\TurboActivate.dll'));
end;
end;