首页 > 其他分享 >Qt设置软件的使用期限--转

Qt设置软件的使用期限--转

时间:2022-12-16 15:57:16浏览次数:47  
标签:const Qt -- int sqlCmd QString QMessageBox 软件 include

https://blog.csdn.net/qq_37033647/article/details/128001563

 

作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

前言
当我们发布商业软件时,为了获取更多的盈利,我们会设置用户使用软件的期限。比如我们给到用户的软件试用期是3个月,过期之后就无法使用了,需要向销售方支付费用,开发者给与授权之后才能继续使用。

对于软件开发者,就博主个人而言,我是非常乐意做这种事情的。博主整理了自己项目中使用的方法,在这里分享一下,也方便自己后期回顾。

功能预览


操作流程
获取设备信息(网卡地址、硬盘序列号、主板序列号、处理器ID、BIOS序列号、CPUID等)
选择使用期限
根据设备信息、使用期限、当前日期生成唯一的 key
把key和所需信息写入注册表
运行程序读取注册表检测是否过期,并更新日期
封装的类 BMachineControl
#include <QString>
#include <QAxObject>
#include <QDebug>
#include <QUuid>
#include <QNetworkInterface>
#include <QCryptographicHash>
#include <QDateTime>
#include <QSettings>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDataStream>
#include <QList>
#include <Windows.h>

class BMachineControl
{
public:
BMachineControl();

QString getWMIHWInfo(int type);

QString getCPUID1();

QString getCPUID2();

QString getHDLogicalID();

QString getMac();

QString getCPUManID();

QString getInfo();

// 根据设备信息、日期、可使用月份生成key
QString getKey(QString machineinfo, QString ddMMyyyy, int months);

// 注册key
bool activeKey(QString key);

// 拷贝至文件
void copyToFile(QSettings* reg, bool magic = false);

// 无注册表信息则初始化并返回true, 否则直接返回false
bool initializeReg();

// 比较是否与文件一致
bool judgeFile();

// 判断日期是否被故意修改
bool judgeDate();

// 判断key,返回剩余天数,过期则为负
int judgeKey();

// 刷新 DT1
void refreshDT1();

private:
const QString kReg = "HKEY_CURRENT_USER\\Software\\Lenovo\\App";
const QString kKey = "K";
const QString kDateTime0 = "DT0";
const QString kDateTime1 = "DT1";
const QString kDateTime2 = "DT2";
const QString kMonths = "M";

const int kForever = 1000000;
const QList<int> kValidity = {1, 3, 6, 12, kForever};

const QString kFile = "C:/ProgramData/Lenovo/app.dat";
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
获取设备信息
这里用到了 QAxObject 和 QNetworkInterface,记得在pro中导入Qt模块
QT += network axcontainer

QString BMachineControl::getWMIHWInfo(int type)
{
/*
* 注意:qt调用wmi时,对查询语句要求很严格,所以like之类的句子务必精确才能有结果出来
*
* 1. 当前原生网卡地址
* SELECT MACAddress ...
*
* 2. 硬盘序列号
* SELECT PNPDeviceID ...
*
* 3. 获取主板序列号
* SELECT SerialNumber ...
*
* 4. 处理器ID
* SELECT ProcessorId ...
*
* 5. BIOS序列号
* SELECT SerialNumber ...
*
* 6. 主板型号
* SELECT Product ...
*/

QString hwInfo;
QStringList sqlCmd;
sqlCmd.clear();
sqlCmd << "SELECT MACAddress FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))";
sqlCmd << "SELECT PNPDeviceID FROM Win32_DiskDrive WHERE( PNPDeviceID IS NOT NULL) AND (MediaType LIKE 'Fixed%')";
sqlCmd << "SELECT SerialNumber FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)";
sqlCmd << "SELECT ProcessorId FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)";
sqlCmd << "SELECT SerialNumber FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)";
sqlCmd << "SELECT Product FROM Win32_BaseBoard WHERE (Product IS NOT NULL)";

QStringList columnName;
columnName.clear();
columnName << "MACAddress";
columnName << "PNPDeviceID";
columnName << "SerialNumber";
columnName << "ProcessorId";
columnName << "SerialNumber";
columnName << "Product";

QAxObject *objIWbemLocator = new QAxObject("WbemScripting.SWbemLocator");
QAxObject *objWMIService = objIWbemLocator->querySubObject("ConnectServer(QString&,QString&)",QString("."), QString("root\\cimv2"));
QString query;
if ( type < sqlCmd.size() ) {
query = sqlCmd.at(type);
}

QAxObject *objInterList = objWMIService->querySubObject("ExecQuery(QString&))", query);
QAxObject *enum1 = objInterList->querySubObject("_NewEnum");

IEnumVARIANT *enumInterface = 0;
enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
enumInterface->Reset();

for ( int i = 0; i < objInterList->dynamicCall("Count").toInt(); ++i )
{
VARIANT *theItem = (VARIANT*)malloc(sizeof(VARIANT));
if ( enumInterface->Next(1, theItem, NULL) != S_FALSE )
{
QAxObject *item = new QAxObject((IUnknown *)theItem->punkVal);
if (item) {
if ( type<columnName.size() ) {
QByteArray datagram(columnName.at(type).toLatin1());
const char* tempConstChar = datagram.data();
hwInfo=item->dynamicCall(tempConstChar).toString();
}
}
}
}

return hwInfo;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
生成key
QString BMachineControl::getKey(QString machineinfo, QString ddMMyyyy, int months)
{
QString originalStr120;
if ( machineinfo.isEmpty() ) {
originalStr120 = QString("machineinfo") + ddMMyyyy + QString::number(months);
} else {
originalStr120 = machineinfo + ddMMyyyy + QString::number(months);
}
QCryptographicHash sha1(QCryptographicHash::Sha1);

QByteArray datagram(originalStr120.toLatin1());

for ( int i = 0; i != datagram.size(); ++i )
{
datagram[i] = datagram[i] ^ 'q' ^ 'y';
}

const char* tempConstChar = datagram.data();
sha1.addData(tempConstChar);

QString activeCode = sha1.result().toHex();

return activeCode;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
在软件启动时检测是否过期
#include "mainwindow.h"
#include <QApplication>
#include <QMessageBox>
#include "bmachinecontrol.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

// 读取注册表中设置的软件使用期限
BMachineControl m_machine;

if ( m_machine.initializeReg() ) {
QMessageBox::information(nullptr, "Error", "No key ! ", QMessageBox::Ok);
return 0;
}

if ( !m_machine.judgeFile() ) {
QMessageBox::information(nullptr, "Error", "File Corruption ! ", QMessageBox::Ok);
return 0;
}

if ( !m_machine.judgeDate() ) {
QMessageBox::information(nullptr, "Error", "Invalid Key ! 0 ", QMessageBox::Ok);
return 0;
}

int days = m_machine.judgeKey();
if ( days == -1 ) {
QMessageBox::information(nullptr, "Error", "Invalid Key ! -1 ", QMessageBox::Ok);
return 0;
} else if ( days == -2 ) {
QMessageBox::information(nullptr, "Error", "Invalid Key ! -2 ", QMessageBox::Ok);
return 0;
} else {
if (days <= 7) {
QMessageBox::information(nullptr, "Info", "Days Remaining: " + QString::number(days) + " ! ", QMessageBox::Ok);
}
}

m_machine.refreshDT1();

MainWindow w;
w.show();
return a.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
清空注册表

————————————————
版权声明:本文为CSDN博主「lucky-billy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34139994/article/details/107652484

标签:const,Qt,--,int,sqlCmd,QString,QMessageBox,软件,include
From: https://www.cnblogs.com/ysgd/p/16987566.html

相关文章

  • day08
    ##变量![image-20221216143633096](C:\Users\biao\AppData\Roaming\Typora\typora-user-images\image-20221216143633096.png)![image-20221216144807423](C:\Users\bia......
  • 【推荐】navigator.sendBeacon() 异步发送数据
    navigator.sendBeacon()异步发送数据navigator.sendBeacon()方法可用于通过HTTP将少量数据异步传输到Web服务器。使用sendBeacon() 方法会使用户代理在有机会时异步......
  • Java内省
    IntrospectorJavaJDKIntrospector在开发框架的时候经常会用到Java类的get/set方法设置或者获取值,但是每次都是用反射来完成此类操作或与麻烦,JDK提供了一套API,专门操......
  • 查看显卡信息
    1、启动matlab时,提示libvaerror:/usr/lib/dri/i965_drv_video.soinitfailed2、使用avinfo,提示Theapplicationvainfoisnotinstalled.Itmaybefoundinthefo......
  • 关于airtest群控制ios
    1.安装carthagebrewinstallcarthage2.下载项目gitclonehttps://github.com/facebookarchive/WebDriverAgent./Scripts/bootstrap.sh#如果报错多半是node版本......
  • 力扣---45. 跳跃游戏 II
    给定一个长度为n的0索引整数数组nums。初始位置为nums[0]。每个元素nums[i]表示从索引i向前跳转的最大长度。换句话说,如果你在nums[i]处,你可以跳转到任意nums......
  • windows安装gitblit
    1、Gitblit-Windows版下载gitblithttp://www.gitblit.com/目前最新版本为CurrentRelease1.8.0(2016-06-22) 2、安装和配置gitblit解压gitblit-1.8.0.zip后,如......
  • DRF之视图
    视图两个视图基类APIViewGenericAPIViewAPIView:APIView是RESTframework提供的所有视图的基类,继承自Django的View父类APIView与View的不同之处在于-......
  • 【ESP 保姆级教程 预告】疯狂Node.js服务器篇 ——安装配置VsCode开发环境
    忘记过去,超越自己❤️博客主页​​单片机菜鸟哥,一个野生非专业硬件IOT爱好者​​❤️❤️本篇创建记录2022-06-30❤️❤️本篇更新记录2022-06-30❤️......
  • Django 简介
    Django简介Django是Python语言的Web框架,开源且免费,可以用于满足快速开发网站的需求。Django接管了Web开发过程中的方方面面,所以开发者可以专注于编写应用程序,而不需......