使用Windows Api+Qt做的一个系统备份工具

        重新编辑于2019.05.08,代码有所改变,详细信息请参阅附件链接,不做详述

        由于公司应用大量装机的情况,以前使用ghost软件来处理,但是自从uefi模式出现后ghost已经不能很好的应用了,虽然现在有Acronis软件替代,但是生成的备份文件没有很好的工具去修改,所以遇到需要添加镜像驱动和补丁的时候带来非常大的麻烦。系统自带的dism工具确实好用,但是每次都需要输入命令行输入,效率不能提高。因此根据现在的实际情况,清明三天假连学带做了这款窗口版的备份还原工具,功能目前很很简单,只有备份分区(文件夹)和还原分区功能,下一步会添加驱动添加功能。废话不说,上代码。

 //DismTools.h  qt widget 头文件
 #pragma once

#include <QWidget>
#include <QThread>

#include "ui_DismTools.h"
#include <QString>
#include <QLabel>
#include "BackUp.h"
#include "Restore.h"
#include "BcdBoot.h"

class DismTools : public QWidget
{
Q_OBJECT

public:
DismTools(QWidget *parent = Q_NULLPTR);
~DismTools()
{
thread.quit();
thread.wait();
}
private:
Ui::DismToolsClass ui;
private slots:
void on_BackUp_clicked();
void on_BackUp_finished(const QString&);
void on_Restore_clicked();
void on_Restore_finished(const QString&);
private:
QThread thread;
BackUp *bk;
Restore *restore;
BcdBoot *boot;
signals:
void backSig(const QString &,const QString &);
void restoreSig(const QString &, const QString &);
void bcdbootSig(const QString &);
//PWSTR pszTmpDir = L"C:\\tmp";


};
//dismtools.cpp 代码
#pragma execution_character_set("utf-8")

#include "DismTools.h"
#include "BackUp.h"
#include <QFileInfo>
#include <QFileDialog>

DismTools::DismTools(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);

connect(ui.backUp, &QPushButton::clicked, this, &DismTools::on_BackUp_clicked);
connect(ui.restore, &QPushButton::clicked, this, &DismTools::on_Restore_clicked);
}
void DismTools::on_BackUp_clicked()
{


QString dir = QFileDialog::getExistingDirectory(this, tr("选择备份分区"),
"/home",
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);


QFileInfo fi(dir);
if (!fi.exists())
{
return;
}

QString fileName = QFileDialog::getSaveFileName(this, QString("保存镜像文件"),
"/home/",
QString("镜像文件 (*.wim)"));
QFileInfo fi1(fileName);


bk = new BackUp();
bk->moveToThread(&thread);
connect(&thread, &QThread::finished, bk, &QObject::deleteLater);
connect(this, &DismTools::backSig, bk, &BackUp::doBackUp);
connect(bk, &BackUp::resultReady, this, &DismTools::on_BackUp_finished);
thread.start();
ui.label->setText("镜像备份中...");
ui.backUp->setDisabled(true);
emit backSig(fileName, dir);

}

void DismTools::on_BackUp_finished(const QString &finished)
{
ui.label->setText(finished);
QMessageBox::warning(this, "", finished);
ui.backUp->setDisabled(false);
}

void DismTools::on_Restore_clicked()
{

QString dir = QFileDialog::getExistingDirectory(this, tr("选择恢复分区"),
"/home",
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);


QFileInfo fi(dir);
if (!fi.exists())
{
return;
}

QString fileName = QFileDialog::getOpenFileName(this, QString("选择镜像文件"),
"/home/",
QString("镜像文件 (*.wim)"));
QFileInfo fi1(fileName);


restore = new Restore();
restore->moveToThread(&thread);
connect(&thread, &QThread::finished, restore, &QObject::deleteLater);
connect(this, &DismTools::restoreSig, restore, &Restore::doRestore);
connect(restore, &Restore::resultReady, this, &DismTools::on_Restore_finished);
thread.start();
ui.label->setText("镜像恢复中...");
ui.restore->setDisabled(true);
emit restoreSig(fileName, dir);
}

void DismTools::on_Restore_finished(const QString &finished)
{
ui.label->setText(finished);
QMessageBox::warning(this, "", finished);
ui.restore->setDisabled(false);
int ret = QMessageBox::question(this, "", QString("是否添加引导项?"), QMessageBox::Ok,QMessageBox::No);
if (ret = 0)
{
QString souces = QFileDialog::getExistingDirectory(this, tr("选择Windows系统根目录"),
"/home",
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);



QString bootPath = QFileDialog::getExistingDirectory(this, tr("选择Windows启动分区"),
"/home",
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);
boot = new BcdBoot();
boot->doBcdBoot(souces, bootPath);
connect(boot, &BcdBoot::resultReady, this, [=](const QString &result)
{
QMessageBox::information(this, "", result);
});
return;
}

}

//backup代码
#pragma once
#pragma execution_character_set("utf-8")
#include <qobject.h>
#include <QString>
#include <QMessageBox>
#include "windows.h"
#include "wimgapi.h"
class BackUp:public QObject
{
Q_OBJECT

public slots:
void doBackUp(const QString &pszWimFile,const QString &pszCaptureDir);
signals:
void resultReady(const QString &result);
};

        

//backup.cpp
#include "BackUp.h"

#include <QMessageBox>

void BackUp::doBackUp(const QString &pszWimFile, const QString &pszCaptureDir)
{

bool sucess = true;
const wchar_t * WimFile = reinterpret_cast<const wchar_t *>(pszWimFile.utf16());
const wchar_t * CaptureDir = reinterpret_cast<const wchar_t *>(pszCaptureDir.utf16());
DWORD dwFlags = 0,
dwDisposition = WIM_CREATE_ALWAYS,
dwDesiredAccess = WIM_GENERIC_WRITE,
dwCreateFlags = 0,
dwCaptureFlags = WIM_FLAG_VERIFY,
dwCompressionType = WIM_COMPRESS_LZX,
dwCreationResult = 0,
dwError = 0;
HANDLE    hWim = WIMCreateFile(WimFile,
dwDesiredAccess,
dwDisposition,
dwCreateFlags,
dwCompressionType,
&dwCreationResult);
sucess = hWim;
if (!sucess)
{
//QMessageBox::critical(this, QString("Error!"), QString("BackUp Error with code Create Fail"));
//QMessageBox::critical(NULL, QString("Error!"), QString("Create Image Fail"));
emit resultReady(QString("文件创建失败"));
return;
}


//WIMSetTemporaryPath(hWim, pszTmpDir);
HANDLE hImage = WIMCaptureImage(hWim, CaptureDir, dwCaptureFlags);
sucess = hImage;
if (!sucess)
{
//QMessageBox::critical(NULL, QString("Error!"), QString("BackUp Error with code BackUp Status"));
emit resultReady(QString("备份失败"));
return;
}

WIMCloseHandle(hImage);

WIMCloseHandle(hWim);
emit resultReady(QString("备份成功"));
}
}

            bcdboot 代码就不贴了,简单的都不不好意思。。。


附件有详细代码  测试环境  vs2017+qt msvc2017 +wadk环境,由于制作内部使用,因此界面比较丑陋,有时间优化吧


        运行效果图111.PNG222.PNG


附件链接:代码