qt做的软件的更新程序!
以前写的一个更新程序 希望可以给需要的朋友一点帮助!
更新的是一个主程序的辅助程序及辅助程序的配置文件和dll 有一些细节就是当主程序的辅助程序需要更新的时候 需要告诉主程序暂时不能调用辅助程序 并且在更新完毕之后告诉主程序可以调用了 其他细节包括无边窗移动啊 状态码返回什么的需要的可以仔细看看我写的代码吧
大体思路是这样的 (图不重要看字)
直接源码
.pro
#-------------------------------------------------
#
# Project created by QtCreator 2015-08-27T08:50:20
#
#-------------------------------------------------
QT += core gui
QT += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Sdup
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
RESOURCES += \
photo.qrc
.h
#ifndefMAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QSettings>
#include<QNetworkAccessManager>
#include<QNetworkReply>
#include<QNetworkRequest>
#include<QDebug>
#include<QStringList>
#include<QVariant>
#include<QVariantMap>
#include<QJsonDocument>
#include<QJsonParseError>
#include<QFile>
#include<QMessageBox>
#include<QTextCodec>
#include<QEventLoop>
#include<QFileInfo>
#include<QDir>
#include<QString>
#include<QPoint>
#include<QMouseEvent>
#include<QPalette>
#include<QBrush>
#include<QPainter>
#include<QProcess>
//
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString read_configure();//获取更新配置文件
void postallconfigure();//发送需要检测的信息接收返回信息
void checkallbackdata();//处理所有的返回的结果 比较版本号和挑出需要更新的版本号!
void copytoanother(const QString &source,const QString &destination);//复制文件到另一个文件夹
bool downfiles(QString url,QString downfilename);//下载需要更新的文件!
void writeinifile(QString name,QString verson);//判断文件是不是新增并更改配置文件的名字和版本号
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
QPoint windowPos;
QPoint mousePos ;
QPoint dPos;
void paintEvent(QPaintEvent *event);
private slots:
void updateprogressBar(qint64 bytesRead, qint64 totalBytes);
private:
Ui::MainWindow *ui;
QString checkurl;
int updatefilenumber;//需下载的更新文件数量
QStringList newfiles;//新增的文件
QStringList failfiels;//下载失败的文件
QProcess *testprocess;
};
#endif // MAINWINDOW_H .cpp #include "mainwindow.h"#include "ui_mainwindow.h"/*
* 配置文件 更新程序的 Sdup.yanxuetao更新配置文件 同级文件夹两个 Downtemp SDLL 均可自动创建* D58的 city.ini AllCity.abcd 城市转换得时候使用的 wubajiami.jde 解密使用 记得调用的时候把D58.dll改为1.dll* 记得测试配置文件 不存在* 配置文件为空 (记得记录返回内容)* 如果配置文件为空的话(可能所有的dll都被删了)重新生成配置文件遍历dll所在文件夹获取现存的所有的文件全部标为最低配 然后检测更新* 配置文件不存在的时候记得配置文件中的信息初始化 检测url分区* 接的要写检测群发更新网址的 更新* 更改程序中加载dll以及dll所需的配置文件的路径 修改为SDLL/dll名字*/
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow){
ui->setupUi(this);// testprocess=new QProcess(this);// connect(testprocess,SIGNAL(finished(int)),this,SLOT(test()));// testprocess->start("F:/111111111111111111111111foryfds/fabunew/Sdup.exe");// qDebug()<< testprocess->state();// qDebug()<<testprocess->isOpen();ui->progressBar->hide();ui->label ->setStyleSheet("color: rgb(235, 235, 117);font-size : 24px");ui->label_2->setStyleSheet("color: rgb(0, 255, 127);font-size : 24px");ui->label_3->setStyleSheet("color: rgb(0,255,255);font-size : 22px");this->setWindowOpacity(1);this->setWindowFlags(Qt::FramelessWindowHint);this->setAttribute(Qt::WA_TranslucentBackground);this->setAutoFillBackground(true);
this->read_configure();//this->read_configure();//this->checkallbackdata();//this->copytoanother("ww.txt","123/w2220w.txt");
//this->downfiles("http://192.168.1.30:8017/userfile/2016/8/16/1.png","1.png");//this->writeinifile("1","1.0");//this->writeinifile("6","666");//this->writeinifile("闫雪涛","闫雪涛");}
MainWindow::~MainWindow(){
delete ui;}
//获取所有的可能更新的数据
QString MainWindow::read_configure(){
QJsonDocument tojson;QVariantMap allsenddata;QFile configuresfile("Sdup.yanxuetao");
if(configuresfile.exists()){//存在为空或者有错误!!!QSettings configures("Sdup.yanxuetao", QSettings::IniFormat);QTextCodec *codec = QTextCodec::codecForName("gb2312");configures.setIniCodec(codec);qDebug()<< configures.NoError<<1111111111111<<configures.status();configures.beginGroup("Dll");qDebug()<<configures.group()<<configures.allKeys()<<configures.value("1");//数据封装qDebug()<<checkurl;
for (int alldll=0;alldll<configures.allKeys().size();alldll++){qDebug()<<"allsenddata0000000000";allsenddata.insert(configures.allKeys().at(alldll),configures.value(configures.allKeys().at(alldll)));qDebug()<<allsenddata;}tojson=QJsonDocument::fromVariant(allsenddata);qDebug()<< tojson.toJson();configures.endGroup();configures.beginGroup("Url");checkurl=configures.value("CheckUrl").toString();qDebug()<<checkurl;return QString(tojson.toJson());}else{//不存在//创建配置文件configuresfile.open(QIODevice::WriteOnly);configuresfile.flush();configuresfile.close();QSettings addnewfiles("Sdup.yanxuetao", QSettings::IniFormat);QTextCodec *codec = QTextCodec::codecForName("gb2312");addnewfiles.setIniCodec(codec);//写入固定的检测群发是否有更新的网址addnewfiles.beginGroup("Dll");addnewfiles.setValue("YfFf.exe","1.0");addnewfiles.endGroup();addnewfiles.beginGroup("Url");addnewfiles.setValue("CheckUrl","http//:test.**");addnewfiles.endGroup();//遍历存放dll的文件夹 不存在就创建新的存放文件夹 文件夹内容为空就什么都没有喽 发送为空的时候记得返回的要有些基本的dll返回过过来下载QDir alldllsdir;if(!alldllsdir.exists("SDLL")){alldllsdir.mkdir("SDll");//低配置来写配置文件 还是写入检测网址qWarning("群发dll不存在!!已创建SDLL文件夹!!");
}else{//[Url]//CheckUrl=http//:test.**//遍历存放dll的文件夹 取出文件 按低版本写入文件alldllsdir.setFilter(QDir::Files | QDir::NoSymLinks);alldllsdir.setPath("SDLL");QFileInfoList list = alldllsdir.entryInfoList();addnewfiles.beginGroup("Dll");for(int i=0; i<list.count(); i++){qDebug()<< list.at(i).fileName();//低配置装进配置问文件中addnewfiles.setValue(list.at(i).fileName(),QString("1.0"));}}QSettings configures("Sdup.yanxuetao", QSettings::IniFormat);configures.setIniCodec(codec);configures.beginGroup("Dll");qDebug()<<configures.group()<<configures.allKeys()<<configures.value("1");//数据封装qDebug()<<checkurl;
for (int alldll=0;alldll<configures.allKeys().size();alldll++){
allsenddata.insert(configures.allKeys().at(alldll),configures.value(configures.allKeys().at(alldll)));
}tojson=QJsonDocument::fromVariant(allsenddata);qDebug()<< tojson.toJson();configures.endGroup();configures.beginGroup("Url");checkurl=configures.value("CheckUrl").toString();qDebug()<<checkurl<<QString(tojson.toJson());return QString(tojson.toJson());}}
void MainWindow::postallconfigure(){
QNetworkAccessManager *postmanager=new QNetworkAccessManager(this);QEventLoop postevent;//设置循环事件//先按post来写 要不要设置验证啥的QNetworkReply *getcheckeddata=postmanager->post(QNetworkRequest(QUrl(checkurl)),this->read_configure().toLatin1());QObject::connect(getcheckeddata,SIGNAL(finished()),&postevent,SLOT(quit()));postevent.exec();if(getcheckeddata->error()==QNetworkReply::NoError)//先判断是不是有错返回{//获取所有的结果!QString allbackdata=getcheckeddata->readAll();qDebug()<<allbackdata;//处理接收到结果!!}else{//有错的处理!!qWarning()<<"接受返回更新数据有误!!";exit(0);}
}
void MainWindow::checkallbackdata(){
QString allbackdata("{\"1111.dll\": \"2.0\",\"CheckUrl\": \"http//:www.yxttest.com\",\"2.dll\": \"2.0\",\"31.dll\": \"3.0\",\"sda.exe\": \"2.0\",\"sda1.exe\": \"2.0\",\"sda2.exe\": \"2.0\",\"sda3.exe\": \"2.0\",\"sda4.exe\": \"2.0\",\"sda5.exe\": \"2.0\",\"DownUrl\": \"http://192.168.1.30:8017/userfile/2016/8/16/\"}");QJsonParseError jsonerror;QJsonDocument checkjsondocument = QJsonDocument::fromJson(allbackdata.toUtf8(), &jsonerror);if (jsonerror.error == QJsonParseError::NoError){if (checkjsondocument.isObject()){QVariantMap result = checkjsondocument.toVariant().toMap();QVariantMap::Iterator aa;qDebug ()<<result.size()<<result.keys()<<result.values()<<result["DownUrl"].toString()<<"10234646";//下载需要更新的文件 修改配置文件QString downurl=result["DownUrl"].toString();int i=0;allbackdata.contains("CheckUrl")? updatefilenumber =result.size()-2: updatefilenumber =result.size()-1;
qDebug()<<"需要更新文件数量为:"<<updatefilenumber;int number=updatefilenumber;ui->progressBar->show();ui->label->setText(QString("需更新:%1").arg(QString::number(updatefilenumber)));ui->label_2->setText(QString("剩余:%1").arg(QString::number(updatefilenumber)));for( aa=result.begin();aa!=result.end();aa++){if(aa.key()!=QString("DownUrl")){if(aa.key()==QString("CheckUrl")){//如果检测更新的网址变了this->writeinifile(QVariant(aa.key()).toString(),QVariant(aa.value()).toString());}else{qDebug()<< aa.key()<<aa.value();//判断是不是新文件//找到文件 转移到临时文件夹QFile::exists(QString("SDLL/").append( aa.key()))? aa.key()==QString("YfFf.exe")?this->copytoanother( QVariant(aa.key()).toString(),QString("DownTemp/").append(QVariant(aa.key()).toString())): this->copytoanother(QString("SDLL/").append( QVariant(aa.key()).toString()),QString("DownTemp/").append(QVariant(aa.key()).toString())):qDebug("新文件");
//下载if( this->downfiles(result["DownUrl"].toString().append(aa.key()),aa.key())){//如果下载成功!!if(QFile::exists(QString("DownTemp/%1").arg(aa.key()))){qDebug()<<"下载成功,正在移除临时文件!!!"<<i;QFile::remove(QString("DownTemp/%1").arg(aa.key()));}else{qDebug()<<"新文件下载完毕!!";}//更改版本配置文件this->writeinifile(QVariant(aa.key()).toString(),QVariant(aa.value()).toString());}else{//下载不成功!! 配置文件不变 下次继续更新qDebug()<<"下载失败!!";failfiels.push_back(aa.key());//记录失败的文件//把原来的文件移回来 并删除临时文件夹里的文件if(aa.key()!=QString("YfFf.exe")){this->copytoanother(QString("DownTemp/%1").arg(QVariant(aa.key()).toString()),QString("SDLL/").append(QVariant(aa.key()).toString()));}else{this->copytoanother(QString("DownTemp/%1").arg(QVariant(aa.key()).toString()),QVariant(aa.key()).toString());}
//源版本号不变!!qWarning()<<"部分文件更新失败!下次次启动会自动更新!!";}//if(ok)删除临时文件夹的文件并且修改版本号 不成功 就从临时文件夹挪回来 记录失败文件i++;--updatefilenumber;ui->label_2->setText(QString("剩余:%1").arg(QString::number(updatefilenumber)));}}}qDebug()<<failfiels; //要不要记录版本号了啊ui->label_3->setText(QString("更新完毕!成功%1个!失败%2个!").arg(QString::number(number-failfiels.size())).arg(failfiels.size()));exit(0);}}else{qWarning()<<"群发更新出错!!返回数据有误!!"<<jsonerror.error<<jsonerror.errorString();exit(0);
}}
void MainWindow::copytoanother(const QString &source, const QString &destination){
//根据文件路径来复制文件到指定临时文件夹!避免更新不成功的时候原来的也不能用了QDir newdir;bool checksource=newdir.exists(source);QFileInfo info(destination);
if(checksource){bool check=newdir.exists(info.path());QString source1=QDir::toNativeSeparators(source);if(check)//判断复制到的文件夹是否存在 不存在的话就重新创建一个{if( QFile::copy(source1,destination)){qDebug()<<QString("复制%1成功!正在删除源文件!").arg(source);if( QFile::remove(source1)){qDebug()<<"删除成功!";}}qDebug () <<"新文件被转移到"<<info.path();}else{newdir.mkdir(info.path());if( QFile::copy(source1,destination)){qDebug()<<QString("复制%1成功!正在删除源文件!").arg(source);if( QFile::remove(source1)){qDebug()<<"删除成功!";}}qDebug () <<"新文件被转移到"<<info.path();}}else{qWarning () <<"被复制源文件不存在"<<source;}
}
bool MainWindow::downfiles(QString url,QString downfilename){
qDebug()<<"正在下载文件!!";//群发程序和群发所需的dll不在同一个文件夹 下载和转移的时候对路径要进行转换if(downfilename.contains(".dll")){downfilename=QString("SDLL/").append(downfilename);}
//url 为下载更新文件的地址 downfilename为下载后的图片的名字!QNetworkAccessManager *downmanager=new QNetworkAccessManager(this);QEventLoop postevent;//设置循环事件QNetworkReply *getcheckeddata=downmanager->get(QNetworkRequest(QUrl(url)));connect(getcheckeddata,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateprogressBar(qint64,qint64)));QObject::connect(getcheckeddata,SIGNAL(finished()),&postevent,SLOT(quit()));postevent.exec();
if(getcheckeddata->error()==QNetworkReply::NoError)//先判断是不是有错返回{QByteArray allfiledata=getcheckeddata->readAll();// qDebug()<<allfiledata;//写入文件QFile file(downfilename);if (!file.open(QIODevice::WriteOnly)){return false;}file.write(allfiledata);file.flush();file.close();// qDebug()<<"文件保存成功!!";delete getcheckeddata;return true;}else{//有错的处理!!delete getcheckeddata;return false;}}
void MainWindow::writeinifile( QString name, QString verson){
qDebug()<<"正在修改配置文件!";QSettings addnewfiles("Sdup.yanxuetao", QSettings::IniFormat);QTextCodec *codec = QTextCodec::codecForName("gb2312");addnewfiles.setIniCodec(codec);name==QString("CheckUrl")?addnewfiles.beginGroup("Url"): addnewfiles.beginGroup("Dll");
addnewfiles.setValue(name,verson);qDebug()<<name.append("更新完毕!!");
}
void MainWindow::updateprogressBar(qint64 bytesRead, qint64 totalBytes){
ui->progressBar->setMaximum(totalBytes);ui->progressBar->setValue(bytesRead);}
void MainWindow::mousePressEvent(QMouseEvent *event){this->windowPos = this->pos();this->mousePos = event->globalPos();this->dPos = mousePos - windowPos;}
void MainWindow::mouseMoveEvent(QMouseEvent *event){this->move(event->globalPos() - this->dPos);}
void MainWindow::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.drawPixmap(0,0,width(),height(),QPixmap(":/6.jpg"));
}
void MainWindow::test(){QMessageBox::warning(this,QString("testprocess"),QString(QString::number(testprocess->exitCode())));}
from:http://blog.****.net/yanxuetao_/article/details/52452602