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>