使用Windows Api+Qt做的一个系统备份工具
重新编辑于2019.05.08,代码有所改变,详细信息请参阅附件链接,不做详述
由于公司应用大量装机的情况,以前使用ghost软件来处理,但是自从uefi模式出现后ghost已经不能很好的应用了,虽然现在有Acronis软件替代,但是生成的备份文件没有很好的工具去修改,所以遇到需要添加镜像驱动和补丁的时候带来非常大的麻烦。系统自带的dism工具确实好用,但是每次都需要输入命令行输入,效率不能提高。因此根据现在的实际情况,清明三天假连学带做了这款窗口版的备份还原工具,功能目前很很简单,只有备份分区(文件夹)和还原分区功能,下一步会添加驱动添加功能。废话不说,上代码。
//DismTools.h qt widget 头文件
#pragma once
#include
#include
#include "ui_DismTools.h"
#include
#include
#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
#include
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
#include
#include
#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
void BackUp::doBackUp(const QString &pszWimFile, const QString &pszCaptureDir)
{
bool sucess = true;
const wchar_t * WimFile = reinterpret_cast(pszWimFile.utf16());
const wchar_t * CaptureDir = reinterpret_cast(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环境,由于制作内部使用,因此界面比较丑陋,有时间优化吧
附件链接:代码