NSIS + QT 实现安装卸载程序

NSIS + QT 做安装卸载程序。
NSIS仅仅用于把所有的东西封装为一个EXE。
NSIS打包
QT做有逼格的可视化界面,并且方便实现。

以下是nSIS源码:
icon ".\xxx.ico"  #设置图标
OutFile "setup.exe"  #设置生成程序
SilentInstall silent  #静默安装不出现任何NSIS自带界面
Function .onInit  #NSIS程序安装准备工作
InitPluginsDir  #创建临时目录(内存)用于保存一些必要的库
SetOutPath $PLUGINSDIR  #将文件保存在临时目录中
  File "Qt5Gui.dll"  #我的安装界面必要的库
  File "Qt5Core.dll"
  File "Qt5Widgets.dll"
  File "Qt5Widgets.dll"
  File "qt.conf"
  File /r "plugins\"
  File "UnRAR.exe"
  File "xxx.rar"  #rar.exe生成的必要的库和文件。
  File "xxx.exe"
FunctionEnd
Function .onInstSuccess  #安装成功后调用
call fun
Functionend
Function fun
   ExecWait $PLUGINSDIR\class8_setup.exe  #调用QT安装程序,等待其运行完后运行下一条语句
   RMDir $PLUGINSDIR                 #释放临时目录(内存)  
FunctionEnd
section
sectionend


出现图标不显示的问题的时候:
在开始里运行tskill ex*
QT做安装程序:
1.必要库的解压。
2.进度条
3.写注册表或配置文件。


这里直接调用第三方的UnRAR.exe程序。QT开一个进程调用它,并且绑定它的标准输出内容到主程序槽,用于设置进度条。
当该程序结束时会返回一个结束信号。


附:
rar unrar命令
rar -help
unrar -help
可以看到详细内容

按照上文的方法,即写两个EXE程序。一个发布的程序,一个是安装程序,安装程序用于解压发布的程序的压缩包。
 

QT源码:

#ifndef ENV
#define ENV
 
#include <QDir>
#include <QString>
#include <QStringList>
#include <QDebug>
 
#include <windows.h>
#include "psapi.h"
#include "stdio.h"
#include <tlhelp32.h>
#include <QStandardPaths>
 
#include <QByteArray>
#include <QFile>
#include <QCryptographicHash>
 
namespace ENV{
 
//define
 
//创建文件夹
static inline void createFolder(const QString &folderPath);
//查找当前是否有该进程运行
static inline bool findProcess(const QString &proName);
//创建桌面快捷方式
static inline bool createShortCutToDeskTop(const QString &file);
//创建开始菜单快捷方式
static inline bool createShortCutToStartMenue(const QString &file);
//得到文件md5
static inline QByteArray getFileMd5(QFile &file);
static inline QByteArray getFileMd5(const QString &filePath);
//对比文件md5
static inline bool cmpFileMd5(QFile &lhs,QFile &rhs);
static inline bool cmpFileMd5(const QString &lhs,const QString &rhs);
 
 
 
//implementation
void createFolder(const QString &folderPath){
    QDir dir;
    bool exist = dir.exists(folderPath);
    if(!exist){
        QStringList list = folderPath.split('/');
        QString filePath = "";
        int len = 0;
        if(QString(list.at(list.length()-1)).contains('.'))
            len = list.length()-1;
        else
            len = list.length();
        for(int i = 0;i < len;++i){
            filePath = filePath + list[i] + '/';
            exist = dir.exists(filePath);
            if(!exist)
                dir.mkdir(filePath);
        }
    }
}
 
static inline bool findProcess(const QString &proName)
{
    int count = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hProcessSnap == INVALID_HANDLE_VALUE)
    {
        count += 0;
    }
    BOOL bMore = ::Process32First(hProcessSnap, &pe32);
    while(bMore)
    {
        if(proName == QString::fromWCharArray(pe32.szExeFile)){
            ++count;
        }
        bMore = ::Process32Next(hProcessSnap, &pe32);
    }
    if(count == 1){
        return true;
    }else if(count > 1){
        return false;
    }
}
 
 
bool createShortCutToDeskTop(const QString &file){
    QString deskTopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    QStringList temp = file.split(":/");
    QStringList temp1 = temp[temp.size()-1].split('.');
    return QFile::link(file,deskTopPath+"/"+temp1[0]+".lnk");
}
 
bool createShortCutToStartMenue(const QString &file){
    QString startMenuePath = "C:/ProgramData/Microsoft/Windows/Start Menu/Programs";
    QStringList temp = file.split(":/");
    QStringList temp1 = temp[temp.size()-1].split('.');
    return QFile::link(file,startMenuePath+"/"+temp1[0]+".lnk");
}
 
 
QByteArray getFileMd5(QFile &file)
{
    if(!file.exists())
        return "";
    file.open(QIODevice::ReadOnly);
    QByteArray result = QCryptographicHash::hash(file.readAll(),QCryptographicHash::Md5);
    file.close();
    return result;
}
 
QByteArray getFileMd5(const QString &filePath){
    return getFileMd5(QFile(filePath));
}
 
bool cmpFileMd5(QFile &lhs,QFile &rhs)
{
    if(!lhs.exists() || !rhs.exists())
        return false;
    return (getFileMd5(lhs) == getFileMd5(rhs));
}
 
bool cmpFileMd5(const QString &lhs,const QString &rhs){
    return cmpFileMd5(QFile(lhs),QFile(rhs));
}
 
}
 
 
#endif // ENV
 

#ifndef SETUP_H
#define SETUP_H
 
#include <qdebug.h>
 
#include <QString>
 
class SetUp{
public:
    explicit SetUp();
    ~SetUp();
 
    void setConfigPath(const QString &configPath);
    void setFilesPath(const QString *filesPaths,unsigned int num);
    void setRegeditData(const QString &itemPath);
 
    bool moveFile(const QString &filePath)const;
    void moveFile()const;
 
    bool createShortCut()const;
    bool createMenueShortCut()const;
 
    bool checkMutex()const;
private:
 
    QString m_cfgPath;
    QString *m_filesPaths;
    unsigned int m_num;
 
private:
    SetUp& operator =(const SetUp &){return *this;}
    SetUp(const SetUp&){}
};
 
#endif // SETUP_H

#include "setup.h"
#include "configfile.h"
#include "registryfile.h"
#include <QFile>
#include <QStandardPaths>
 
#include "env.h"
 
SetUp::SetUp():m_filesPaths(NULL),m_cfgPath(""),m_num(0)
{
 
}
 
SetUp::~SetUp()
{
    if(m_filesPaths)
    {
        delete []m_filesPaths;
        m_filesPaths = NULL;
    }
}
 
void SetUp::setConfigPath(const QString &configPath)
{
    m_cfgPath = configPath;
}
 
void SetUp::setFilesPath(const QString *filesPaths,unsigned int num)
{
    if(NULL == filesPaths)
        return;
    m_num = num;
    m_filesPaths = new QString[m_num];
    for(unsigned int i = 0;i < m_num;++i)
    {
        this->m_filesPaths[i] = filesPaths[i];
    }
}
 
bool SetUp::moveFile(const QString &filePath)const
{
    if(!QFile::exists(filePath))
        return false;
    QStringList temp = filePath.split(":/");
    ENV::createFolder(m_cfgPath+'/'+temp[temp.size()-1]);
    bool flag = QFile::copy(filePath,m_cfgPath+'/'+temp[temp.size()-1]);
 
    if(flag){
        return true;
    }
    return false;
}
 
void SetUp::moveFile()const
{
    for(unsigned int i = 0;i < m_num;++i)
        moveFile(m_filesPaths[i]);
}
 
bool SetUp::createShortCut()const{
    QString deskTopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    QStringList temp = m_filesPaths[m_num-1].split(":/");
    return QFile::link(m_cfgPath+'/'+temp[temp.size()-1],deskTopPath+"/"+"jojojojo.lnk");
}
 
bool SetUp::createMenueShortCut()const
{
    return true;
}
 
void SetUp::setRegeditData(const QString &itemPath)
{
    ConfigFile *configFile = new RegistryFile(itemPath);
    if(configFile->init())
        configFile->setValue("cfgPath",m_cfgPath);
    delete configFile;
}
 
 
bool SetUp::checkMutex()const
{
    return ENV::findProcess("setup_ui.exe");
}

#ifndef CONFIGFILE_H
#define CONFIGFILE_H
 
#include <QString>
#include <QMap>
#include <QSettings>
 
class ConfigFile
{
public:
    explicit ConfigFile();
    virtual ~ConfigFile();
 
    virtual bool init() = 0;
 
    virtual bool setValue(const QString &valueName,const QVariant &defaultValue) = 0;
    virtual bool getValue(const QString &valueName,QVariant &outValue)const = 0;
    virtual bool getAllValue(QMap<QString,QVariant> &outValues)const = 0;
 
    virtual bool createItem(const QString &ItemPath) = 0;
 
protected:
    QSettings *m_settings;
    QString m_filePath;
    bool m_exists;
};
 
#endif // CONFIGFILE_H

#include "configfile.h"
 
ConfigFile::ConfigFile()
    :m_settings(NULL),m_filePath(""),m_exists(false)
{
 
}
 
ConfigFile::~ConfigFile()
{
    if(m_settings)
    {
        delete m_settings;
        m_settings = NULL;
    }
}


#ifndef INIFILE_H
#define INIFILE_H
 
#include <configfile.h>
 
class IniFile : public ConfigFile
{
public:
    explicit IniFile(const QString &filePath = "");
    ~IniFile();
 
    bool init();
 
    bool setValue(const QString &valueName,const QVariant &defaultValue);
    bool getValue(const QString &valueName,QVariant &outValue)const;
    bool getAllValue(QMap<QString,QVariant> &outValues)const;
 
    bool createItem(const QString &ItemPath);
 
private:
    IniFile(const IniFile&){}
    IniFile& operator=(const IniFile&){return *this;}
};
 
#endif // INIFILE_H

#include "inifile.h"
#include <QFile>
 
IniFile::IniFile(const QString &filePath)
    :ConfigFile()
{
    this->m_filePath = filePath;
}
 
IniFile::~IniFile()
{
 
}
 
bool IniFile::init()
{
    if(QFile::exists(m_filePath))
        m_exists = true;
    else
        return false;
    m_settings = new QSettings(m_filePath, QSettings::IniFormat);
    return true;
}
 
bool IniFile::setValue(const QString &valueName,const QVariant &defaultValue = QVariant())
{
    if(!m_exists)
        return false;
    m_settings->setValue(valueName,defaultValue);
    return true;
}
 
bool IniFile::getAllValue(QMap<QString,QVariant> &outValues)const
{
    if(!m_exists)
        return false;
    foreach(QString str,m_settings->childKeys())
    {
        outValues.insert(str,m_settings->value(str));
    }
    return true;
}
 
bool IniFile::getValue(const QString &valueName,QVariant &outValue)const
{
    if(!m_exists)
        return false;
    foreach(QString str,m_settings->childKeys())
    {
        if(valueName == str)
        {
            outValue = m_settings->value(str);
            return true;
        }
    }
    return false;
}
 
bool IniFile::createItem(const QString &ItemPath){
    QFile file(ItemPath);
    if(file.exists())
        return false;
    file.open(QIODevice::WriteOnly);
    file.close();
    this->m_filePath = ItemPath;
    return true;
}

#ifndef REGISTRYFILE_H
#define REGISTRYFILE_H
 
#include <configfile.h>
 
class RegistryFile : public ConfigFile
{
public:
    explicit RegistryFile(const QString &filePath);
    ~RegistryFile();
 
    bool init();
 
    bool setValue(const QString &valueName,const QVariant &defaultValue);
    bool getValue(const QString &valueName,QVariant &outValue)const;
    bool getAllValue(QMap<QString,QVariant> &outValues)const;
 
    bool createItem(const QString &ItemPath);
 
private:
    RegistryFile(const RegistryFile&){}
    RegistryFile& operator=(const RegistryFile&){return *this;}
};
 
#endif // REGISTRYFILE_H

#include "registryfile.h"
#include <QFile>
RegistryFile::RegistryFile(const QString &filePath)
    :ConfigFile()
{
    this->m_filePath = filePath;
}
 
RegistryFile::~RegistryFile(){
 
}
 
bool RegistryFile::init()
{
    m_settings = new QSettings(m_filePath, QSettings::NativeFormat);
    return true;
}
 
bool RegistryFile::setValue(const QString &valueName,const QVariant &defaultValue = QVariant())
{
    m_settings->setValue(valueName,defaultValue);
    return true;
}
 
bool RegistryFile::getAllValue(QMap<QString,QVariant> &outValues)const
{
    foreach(QString str,m_settings->childKeys())
    {
        outValues.insert(str,m_settings->value(str));
    }
    return true;
}
 
bool RegistryFile::getValue(const QString &valueName,QVariant &outValue)const
{
    foreach(QString str,m_settings->childKeys())
    {
        if(str == valueName)
        {
            outValue = m_settings->value(str);
            return true;
        }
    }
    return false;
}
 
bool RegistryFile::createItem(const QString &ItemPath){
    QSettings *tempSetting = new QSettings(ItemPath,QSettings::NativeFormat);
    delete tempSetting;
    return true;
}

#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
 
class QMovie;
class QProcess;
class SetUp;
 
namespace Ui {
class Dialog;
}
 
class Dialog : public QDialog
{
    Q_OBJECT
 
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
 
private slots:
    void on_pushButton_clicked();
    void uncompressFinished();
    void uncompressSuccess();
 
private:
    Ui::Dialog *ui;
    QMovie *m_movie;
    QProcess *m_pro;
    SetUp *m_setUp;
    bool m_isOver;
    int count;
};
 
#endif // DIALOG_H

#include "dialog.h"
#include "ui_dialog.h"
 
#include <QStandardPaths>
#include <QProcess>
#include <QMovie>
#include "setup.h"
#include "env.h"
 
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),count(0),m_setUp(NULL),
    ui(new Ui::Dialog),m_isOver(false)
{
    ui->setupUi(this);
    m_movie=new QMovie(":/background.gif");
    ui->progressBar->setMaximum(465);
    ui->progressBar->setValue(0);
    ui->gif->setMovie(m_movie);
    this->setWindowIcon(QIcon(":/class8big.ico"));
    m_movie->start();
    m_pro = new QProcess;
    connect(m_pro,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(uncompressFinished()));
    connect(m_pro,SIGNAL(readyReadStandardOutput()),this,SLOT(uncompressSuccess()));
    m_setUp = new SetUp;
}
 
Dialog::~Dialog()
{
    delete ui;
    delete m_setUp;
}
 
void Dialog::uncompressFinished(){
    qDebug()<<"install success!";
    ui->progressBar->setValue(ui->progressBar->maximum());
    ui->pushButton->setText("安装成功");
    m_isOver = true;
    delete m_pro;
}
 
void Dialog::uncompressSuccess(){
    qDebug()<<++count;
    ui->progressBar->setValue(count);
}
 
void Dialog::on_pushButton_clicked()
{
    if(!m_isOver){
     if(m_setUp->checkMutex()){
         qDebug()<<"mutex"<<endl;
     }
     QString configPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
     QString itemPath = "HKEY_CURRENT_USER\\Software\\calss8";
 
     QStringList list = configPath.split('/');
     QString setupPath = "";
     for(int i = 0;i < list.size()-1;++i)
         setupPath += list[i] + '/';
     setupPath += "Class9";
     QString runPath = QCoreApplication::applicationDirPath();
     ENV::createFolder(setupPath);
     m_setUp->setConfigPath(setupPath);
     m_setUp->setRegeditData(itemPath);
 
     QString cmd = runPath + '/' + "unrar" + " x -y " + runPath+"/class8.rar "+setupPath;
     qDebug()<<cmd;
     m_pro->start(cmd);
    }
    else
        this->close();
}



<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>363</width>
    <height>283</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <layout class="QHBoxLayout" name="horizontalLayout_2">
   <item>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QLabel" name="gif">
       <property name="text">
        <string>TextLabel</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QProgressBar" name="progressBar">
       <property name="value">
        <number>24</number>
       </property>
      </widget>
     </item>
     <item>
      <layout class="QHBoxLayout" name="horizontalLayout">
       <item>
        <spacer name="horizontalSpacer">
         <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
           <width>40</width>
           <height>25</height>
          </size>
         </property>
        </spacer>
       </item>
       <item>
        <widget class="QPushButton" name="pushButton">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="minimumSize">
          <size>
           <width>60</width>
           <height>25</height>
          </size>
         </property>
         <property name="maximumSize">
          <size>
           <width>60</width>
           <height>25</height>
          </size>
         </property>
         <property name="text">
          <string>开始安装</string>
         </property>
        </widget>
       </item>
      </layout>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值