Protect a Qt C++ Windows application

Following is a step-by-step procedure to protect a Qt C++ Windows app. Note that the steps below assume you have a QLM License Server already set up.

1. Launch the QLM Management Console

2. Create a product from the “Define Product” tab or use the Demo 1.0 product if you are evaluating QLM.

3. Go to the "Protect your application tab":

  • Page 1: Select the product to protect and the License Server

  • Page 2: Select "Qt C++ Windows Only"

  • Page 3: Leave the default settings or customize the look & feel if needed

  • Page 4: Select the folder where your Qt C++ source code is located and click Save

  • Page 5: Click Finish

4. Copy the following files to your debug or release folder:

  • C:\Program Files\Soraco\QuickLicenseMgr\Redistrib\.net 4.0\QlmLicenseWizard.exe

  • C:\Program Files\Soraco\QuickLicenseMgr\Redistrib\.net 4.0\QlmLicenseLib.dll

  • "Your Product x.y.xml" - this is the XML settings file generated by the "Protect your application" wizard

5. Open a command prompt as Administrator (Run As Administrator) and execute the register.bat batch file located in the sample folder.

6. Open your Qt C++ project in your IDE

7. Add the following to your main MainWindow class header file:

namespace Qlm {
class LicenseValidator;
}

In your main class, add the following functions:

private slots:
    bool checkLicense();
    bool checkFiles ();
    void exitApp();
    void displayMessage (QString msg);

private:
    Qlm::LicenseValidator *lv;
    QString wizardSettingsFile;
    QString wizardExe;

8. Add the following code to your MainWindow CPP file, in the constructor:

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString appFolder = QDir::currentPath();

    // You can modify these paths depending on where you deploy the QLM files.
    wizardSettingsFile = QDir(appFolder).filePath("Demo 1.0.lw.xml");

    // Note that QlmLicenseLib.dll must be located in the same folder as QlmLicenseWizard.exe
    wizardExe = QDir(appFolder).filePath("QlmLicenseWizard.exe");

    checkFiles();

    lv = new Qlm::LicenseValidator;
    checkLicense ();

}

9. Add the following functions to your main class:

bool MainWindow::checkFiles()
{
    if(QFileInfo(wizardSettingsFile).exists() == false)
    {
        QString msg = QString ("The file \"%1\" does not exist.").arg (wizardSettingsFile);
        displayMessage(msg);
        exitApp ();
        return false;
    }

    if(QFileInfo(wizardExe).exists() == false)
    {
        QString msg = QString ("The file \"%1\" does not exist.").arg (wizardExe);
        displayMessage(msg);
        exitApp ();
        return false;
    }

    // Also make sure that QlmLicenseLib.dll is in the same folder as QlmLicenseWizard.exe
    QString qlmLicenseLibDll = wizardExe;
    qlmLicenseLibDll.replace("QlmLicenseWizard.exe", "QlmLicenseLib.dll");
    if(QFileInfo(qlmLicenseLibDll).exists() == false)
    {
        QString msg = QString ("The file \"%1\" does not exist.").arg (qlmLicenseLibDll);
        displayMessage(msg);
        exitApp ();
        return false;
    }
}

bool MainWindow::checkLicense()
{
    bool needsActivation;
    QString returnMsg;
    bool valid = lv->ValidateLicenseAtStartup (QlmLicenseLib::ELicenseBinding_ComputerName, needsActivation, returnMsg);

    if (valid == false)
    {
        QString args = QString (" /settings \"%1\"").arg (wizardSettingsFile);
        if (lv->license != nullptr)
        { 
            // If the call to LaunchProcess does not launch the wizard
            // the most likely reason is that you have not registered the QlmLicenseLib.dll
            // To register QlmLicenseLib.dll, launch register.bat from a command prompt running
            // as Administrator
            int exitCode = lv->license->LaunchProcess(wizardExe, args, true, true);

            valid = lv->ValidateLicenseAtStartup(QlmLicenseLib::ELicenseBinding_ComputerName,                                             needsActivation, returnMsg);

            if (valid == false)
            {
                QTimer::singleShot(250, qApp, SLOT(quit()));
            }
        }
    }

    if (valid && (returnMsg.length() == 0))
    {
        ui->status_label->setText("The license is valid.");
    }
    else
    {
        ui->status_label->setText(returnMsg);
    }

    return valid;
}

void MainWindow::exitApp()
{
    QTimer::singleShot(250, qApp, SLOT(quit()));
}

void MainWindow::displayMessage (QString msg)
{
    QMessageBox msgBox;
    msgBox.setText("License Error");
    msgBox.setInformativeText(msg);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    int ret = msgBox.exec();
}

This completes the integration. To generate a license key for testing purposes:

  • Go to the Manage Keys tab.

  • Click "Create Activation Key"

  • Select the Product (Demo 1.0 for trials) and click OK.

  • Copy and Paste the generated Activation Key in the License Wizard launched when your application starts up and follow the steps in the wizard.

The files that you need to distribute with your application are:

  • QlmLicenseLib.dll

  • QlmLicenseWizard.exe

  • XML file generated by the Protect Your Application Wizard

Troubleshooting

  • Missing atlbase.h, strongname.h, metahost.h?

For Qt6, when installing Visual Studio, select the Individual Components tab, and under SDKs, libraries, and frameworks make sure Active Qt (Visual C++ ATL Support) is selected.

For Qt 5, you must install the .NET Framework Developer Pack 4.6.2 or later. Once you install it, the file should typically be located in: C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8.1\Include

To further protect your application against hacking, you should check some of the techniques described in the articles below:

Last updated