标签:Widnows API Dism Qt Wimgapi
使用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环境,由于制作内部使用,因此界面比较丑陋,有时间优化吧
运行效果图
附件链接:代码
标签:Widnows API Dism Qt Wimgapi
原文地址:http://blog.51cto.com/amgodchan/2095438