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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Windows Api+Qt做的一个系统备份工具相关的知识,希望对你有一定的参考价值。

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

        由于公司应用大量装机的情况,以前使用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("备份成功"));
}
//restore.h 代码
#pragma once
#pragma execution_character_set("utf-8")
#include <QObject>
#include <QString>
#include "Windows.h"
#include "wimgapi.h"

class Restore : public QObject
{
	Q_OBJECT



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


//restore.cpp
#include "Restore.h"


void Restore::doRestore(const QString &pszWimFile, const QString &pszCaptureDir)
{

	bool sucess = true;
	const wchar_t * WimFile = reinterpret_cast<const wchar_t *>(pszWimFile.utf16());
	const wchar_t * pszApplyDir = reinterpret_cast<const wchar_t *>(pszCaptureDir.utf16());
	HANDLE hWim = NULL,
		hImage = NULL;
	DWORD  dwCreateFlags = 0,
		dwCreateResult = 0,
		dwImageIndex = 1,
		dwError = 0;
	WIM_INFO WimInfo = { 0 };

	hWim = WIMCreateFile(WimFile,          // Existing .wim file to append the image to
		WIM_GENERIC_READ,    // Access mode
		WIM_OPEN_EXISTING,   // Open disposition
		dwCreateFlags,
		0,                   // Compression type is ignored for WIM_OPEN_EXISTING.
		&dwCreateResult);

	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;
	}
	

	WIMGetAttributes(hWim, &WimInfo, sizeof(WimInfo));
	if (WimInfo.ImageCount < dwImageIndex)
	{

		emit resultReady(QString("镜像读取失败"));
		return;
	}
	
	
	WIMSetTemporaryPath(hWim, pszApplyDir);
	hImage = WIMLoadImage(hWim, dwImageIndex);
	
	sucess = hImage;
	if (!sucess)
	{
		//QMessageBox::critical(NULL, QString("Error!"), QString("BackUp Error with code BackUp Status"));
		
		emit resultReady(QString("不能获取镜像索引"));
		return;
	}
	

	WIMApplyImage(hImage, pszApplyDir, WIM_FLAG_FILEINFO);
	//sucess = WIMApplyImage(hImage, pszApplyDir, WIM_FLAG_NO_APPLY);
	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环境,由于制作内部使用,因此界面比较丑陋,有时间优化吧


        运行效果图技术分享图片技术分享图片


附件链接:代码

以上是关于使用Windows Api+Qt做的一个系统备份工具的主要内容,如果未能解决你的问题,请参考以下文章

Windows系统备份的三种方法

Qt 是不是支持 windows 蓝牙 API?

Windows server 2016 活动目录备份及恢复

非常叼的工单系统,工单结束,工作完成;非常叼的权限管控,精细到页面按钮及API

我在windows下用QT写了个程序,把这个源代码直接在linux下编译可以吗?

qt加载第三方sdk的时候,应该将.dll放在哪