1、前言
程序员随着代码写的多,难免会接到一些私活。但是又怕对方白嫖,困难总比办法多,哦不,错了,办法总比困难多。为了避免被别人白嫖,我们可以给自己的程序留后手,网上查阅资料,大概有以下两种:
1、采用远程控制:UDP指令远程锁死程序;
2、采用本地加密:提取CPU和硬盘序列号,加密生成注册码;
以上两种方法各有利弊,方法1可以本人自由控制,但是一旦设备没网,就GG了;方法2则不依赖网络,且每台设备的注册码唯一,但是本人无法直接控制。个人认为还是方法2简单有效,所以下面就方法2进行具体分析。
2、分析
采用注册码机制,我们首先要生成注册码,Qt下获取CPU和硬盘等系统信息(针对windows系统)的方法如下:
windows下执行命令除了用cmd之外,还有个东西叫WMIC,非常强大,可以通过他获取很多信息,包括硬件信息。
QString Widget::getWMIC(const QString &cmd)
{
//获取cpu名称:wmic cpu get Name
//获取cpu核心数:wmic cpu get NumberOfCores
//获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号:wmic cpu get processorid
//查询主板序列号:wmic baseboard get serialnumber
//查询BIOS序列号:wmic bios get serialnumber
//查看硬盘:wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString Widget::getCpuName()
{
return getWMIC("wmic cpu get name");
}
QString Widget::getCpuId()
{
return getWMIC("wmic cpu get processorid");
}
QString Widget::getDiskNum()
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
获取注册码之后,就可以着手程序的加密了,我的策略是这样的:
如果程序没有注册,默认可以使用3次;
如果程序注册了,使用次数无限制;
那怎么限制程序的使用次数呢?我的策略是这样的:
生成一个System.ini配置文件,里面存放程序的剩余运行次数RemainTime:3;
但是RemainTime:3当然不能直接存在System.ini中,不然一眼看出来就可以自己修改次数了;
所以在对System.ini写之前,进行加密;对System.ini读之后,进行解密;
加/解密算法可以自行选取,但是要采用可逆算法;
然后判断剩余运行次数,如果小于等于0,则程序提示需注册后使用,并退出;
否则,剩余运行次数减1,程序正常运行;
3、实现(核心代码)
QString Widget::getWMIC(const QString &cmd)
{
//获取cpu名称:wmic cpu get Name
//获取cpu核心数:wmic cpu get NumberOfCores
//获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
//查询cpu序列号:wmic cpu get processorid
//查询主板序列号:wmic baseboard get serialnumber
//查询BIOS序列号:wmic bios get serialnumber
//查看硬盘:wmic diskdrive get serialnumber
QProcess p;
p.start(cmd);
p.waitForFinished();
QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
QStringList list = cmd.split(" ");
result = result.remove(list.last(), Qt::CaseInsensitive);
result = result.replace("\r", "");
result = result.replace("\n", "");
result = result.simplified();
return result;
}
QString Widget::getCpuId() //获取CPU序列号
{
return getWMIC("wmic cpu get processorid");
}
QString Widget::getDiskNum() //获取硬盘序列号
{
return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
QString Widget::Encode(QString row) //加密,由于加/解密不是本文重点,故简单处理一下
{
QByteArray byteArray = row.toUtf8();
byteArray = byteArray.toBase64();
return byteArray;
}
QString Widget::Decode(QString passwd) //解密
{
QByteArray byteArray = passwd.toUtf8();
byteArray = QByteArray::fromBase64(byteArray);
return byteArray;
}
void Widget::Judge_Valid() //判断程序合法性
{
QString filePath = "System.ini";
QFile file(filePath);
if(!file.exists()) { //如果文件不存在
file.open(QIODevice::ReadWrite | QIODevice::Text); //新建文件
QString info = "RemainTime:"+time; //time是全局变量,QString time = "3";
file.write(Encode(info).toUtf8()); //写入信息
file.close();
goto Here;
}else { //如果文件存在
Here:if(file.open(QFile::ReadWrite | QFile::Text)) { //打开文件
QString info = file.readAll(); //读取信息
if(info.isEmpty()) { //如果文件为空
QString time_temp = "1";
QString info = "RemainTime:"+time_temp;
file.write(Encode(info).toUtf8()); //写入信息
info = file.readAll();
}
info = Decode(info); //解码
if(info.contains(':')) { //信息正确
QStringList list = info.split(':');
if(list.length()>=1) {
if(list[1].toInt() <= 0) { //程序剩余使用次数不足
QMessageBox::about(this,"提示","请注册后再使用!");
exit(0); //程序退出
}else { //程序还有剩余使用次数
file.close();
file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate); //清空文件内容
QString time_remain = QString::number(list[1].toInt()-1); //程序剩余使用次数减1
QString info = "RemainTime:"+time_remain;
file.write(Encode(info).toUtf8()); //更新程序剩余使用次数
QMessageBox::about(this,"提示","程序剩余使用次数:"+time_remain+"次");
}
}
}
}//Here
file.close();
}//如果文件存在
}
4、效果
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓