qt使用wimlib-imagex,做windows系统备份还原

wimlib-imagex是个第三方工具,可对系统映像进行操作,下载地址:
https://wimlib.net/downloads/index.html
在这里插入图片描述
程序主要用到以下这两个文件:libwim-15.dll和wimlib-imagex.exe
在这里插入图片描述
wimlib-imagex.exe的调用命令参数,可以通过cmd命令行wimlib-imagex --help进行查看,也可以自行百度。




系统备份:通过wimlib-imagex的capture命令,对指定系统盘进行捕获映像,生成wim文件。
系统还原:进入winPE系统,对指定系统盘进行格式化,再通过wimlib-imagex的apply命令,将之前备份的完整的wim文件应用到系统盘。


以下为涉及的部分参考代码:

SystemReloadObject.cpp


//系统备份
bool CSystemReloadObject::systemBackup(const QString& backupName, const QString& backupDesc)
{QString sourcePath = getSystemDrive();m_pThread->systemBackup(sourcePath, backupName, backupDesc);return true;
}//系统还原
bool CSystemReloadObject::systemRestore(const QString& backupName, const int& index)
{m_pThread->systemRestore(backupName, index);return true;
}//本地模式下载安装
bool CSystemReloadObject::systemPEDownload()
{m_pThread->systemPEDownload();return true;
}//获取当前系统盘盘符
QString CSystemReloadObject::getSystemDrive()
{char str[MAX_PATH]{0};GetSystemDirectoryA(str, MAX_PATH);return QString::fromStdString(std::string(1, str[0]));
}//获取当前系统版本
QString CSystemReloadObject::getSystemVersion()
{QString vname;//先判断是否为win8.1或win10typedef void(__stdcall* NTPROC)(DWORD*, DWORD*, DWORD*);HINSTANCE hinst = LoadLibrary(L"ntdll.dll");DWORD dwMajor, dwMinor, dwBuildNumber;NTPROC proc = (NTPROC)GetProcAddress(hinst, "RtlGetNtVersionNumbers");proc(&dwMajor, &dwMinor, &dwBuildNumber);if (dwMajor == 6 && dwMinor == 3)	//win 8.1{vname = "Microsoft Windows 8.1";return vname;}if (dwMajor == 10 && dwMinor == 0)	//win 10{vname = "Microsoft Windows 10";return vname;}//判断win8.1以下的版本SYSTEM_INFO info;                //用SYSTEM_INFO结构判断64位AMD处理器GetSystemInfo(&info);            //调用GetSystemInfo函数填充结构OSVERSIONINFOEX os;os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
#pragma warning(disable:4996)int SystemVer = 0;if (GetVersionEx((OSVERSIONINFO*)&os)){//下面根据版本信息判断操作系统名称switch (os.dwMajorVersion){                        //判断主版本号case 4:switch (os.dwMinorVersion){                //判断次版本号case 0:if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) {vname = "Microsoft Windows NT 4.0";  //1996年7月发布SystemVer = 40; // Windows NT 4.0}else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {vname = "Microsoft Windows 95";SystemVer = 95;}break;case 10:vname = "Microsoft Windows 98";SystemVer = 41; // Windows 98break;case 90:vname = "Microsoft Windows Me";SystemVer = 42; // Windows Mebreak;}break;case 5:switch (os.dwMinorVersion){               //再比较dwMinorVersion的值case 0:vname = "Microsoft Windows 2000";    //1999年12月发布SystemVer = 50; // Windows 2000break;case 1:vname = "Microsoft Windows XP";      //2001年8月发布SystemVer = 51; // Windows XPbreak;case 2:if (os.wProductType == VER_NT_WORKSTATION &&info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64){vname = "Microsoft Windows XP Professional x64 Edition";SystemVer = 52;}else if (GetSystemMetrics(SM_SERVERR2) == 0){vname = "Microsoft Windows Server 2003";   //2003年3月发布SystemVer = 53;}else if (GetSystemMetrics(SM_SERVERR2) != 0){vname = "Microsoft Windows Server 2003 R2";SystemVer = 54;}break;}break;case 6:switch (os.dwMinorVersion){case 0:if (os.wProductType == VER_NT_WORKSTATION){vname = "Microsoft Windows Vista";SystemVer = 60; // Windows Vista}else {vname = "Microsoft Windows Server 2008";   //服务器版本SystemVer = 61; // Windows Server 2008}break;case 1:if (os.wProductType == VER_NT_WORKSTATION){vname = "Microsoft Windows 7";SystemVer = 70; // Windows 7}else{vname = "Microsoft Windows Server 2008 R2";SystemVer = 71; // Windows Server 2008 R2}break;case 2:if (os.wProductType == VER_NT_WORKSTATION){vname = "Microsoft Windows 8";SystemVer = 80; // Windows 8}else {vname = "Microsoft Windows Server 2012";SystemVer = 81; // Windows Server 2012}break;}break;default:vname = "未知操作系统";SystemVer = 0;}}else {printf_s("版本获取失败\n");}return vname;
}//获取当前存在的备份
void CSystemReloadObject::getSystemBackup()
{QString backupPath = QDir::currentPath() + "/SystemBackup/";QDir dir(backupPath);QFileInfoList infolist = dir.entryInfoList();QJsonArray backupArray;foreach(auto it, infolist){if(it.suffix() == "wim" || it.suffix() == "WIM"){QJsonObject backupObj;backupObj.insert("name", it.absoluteFilePath());backupArray.append(backupObj);}}emit sigBackupInfo(backupArray);
}//获取当前存在的有效备份的卷
void CSystemReloadObject::getSystemBackupImage(const QString& backupPath)
{//使用wimlib-imagex的info命令检验QString cmd = QString("\"%1/SystemReload/wimlib-imagex.exe\" info \"%2\"").arg(QDir::currentPath()).arg(backupPath);QProcess process;process.start(cmd);process.waitForFinished();QByteArray all = process.readAll();QString strall = QString(all);int indexs = 0;if (!strall.contains("Available Images:")) {qDebug() << "此wim无效,无法进行还原";}else{qDebug() << "有可用的Images";int pos = strall.indexOf("Available Images:");strall = strall.mid(pos);indexs = strall.count("Index:");}//添加数据到modelQJsonArray imageArray;for(int i=0; i<indexs; i++){QJsonObject imageObj;imageObj.insert("name", QString::number(i+1));imageArray.append(imageObj);}emit sigImageInfo(imageArray);
}//检测当前系统是否是winPE环境
bool CSystemReloadObject::isCurrentWinPE()
{HKEY hkey = NULL;unsigned char buffer[260] = { 0 };unsigned long dwsize = sizeof(buffer);std::string strfind;unsigned long iret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control", 0, KEY_READ, &hkey);if (iret != ERROR_SUCCESS)return false;iret = RegQueryValueExA(hkey, "SystemStartOptions", NULL, NULL, buffer, &dwsize);if (iret != ERROR_SUCCESS){RegCloseKey(hkey);return false;}RegCloseKey(hkey);// get registry keys.// next find '/MININT' flag.strfind.assign((char*)buffer);std::transform(strfind.begin(), strfind.end(), strfind.begin(), tolower);// to lowercase.if ((int)strfind.find("minint", 0) > -1){//是winPEemit sigDialogOperte(1);return true;}//不是winPEemit sigDialogOperte(2);return false;
}//检查当前是否存在winPE
bool CSystemReloadObject::hasLocalWinPE()
{//判断系统BCD引导文件是否有winPE的引导菜单QString cmd = QString("bcdedit /enum");QStringList args;args << "/C" << cmd;QString program = "cmd.exe";QProcess process;process.start(program, args);process.waitForFinished();QByteArray all = process.readAll();QString strall = QString(all);if (strall.contains(LOCAL_WINPE_DEVICE_GUID) || strall.contains(LOCAL_WINPE_OSLOADER_GUID)) {qDebug() << "当前存在winpe本地模式";emit sigDialogOperte(3);return true;}emit sigDialogOperte(4);return false;
}//打开备份文件位置
void CSystemReloadObject::openBackupFilePath()
{QString strPath = QDir::currentPath() + "/SystemBackup";strPath.replace("/", "\\");QProcess process;process.startDetached("explorer", QStringList() << QString("/select,") << QString("%1").arg(strPath));
}//关闭线程启用的外部程序
void CSystemReloadObject::exitApp()
{m_pThread->killProcess();
}//重启电脑
void CSystemReloadObject::restartComputer()
{QString cmd = "shutdown /r /t 0";QStringList args;args << "/C" << cmd;QString program = "cmd.exe";QProcess process;process.start(program, args);process.waitForFinished();
}

SystemReloadThread.cpp
void CSystemReloadThread::systemBackup(const QString& sourcePath, const QString& backupName, const QString& backupDesc)
{m_threadParams.clear();m_threadParams.append(sourcePath);m_threadParams.append(backupName);m_threadParams.append(backupDesc);m_memberFun = &CSystemReloadThread::systemBackup;this->start();
}bool CSystemReloadThread::systemBackup(QVariantList params)
{//创建备份文件夹QDir tempDir(m_BackupFilePath);if (!tempDir.exists()) {if (!tempDir.mkpath(m_BackupFilePath)) {qDebug() << "failed to create backupDir";sigDialogResultThread(1,0);emit sigUpdateBtn(true);return false;}}QString filepath = m_BackupFilePath + params[1].toString() + ".wim";QFile wimFile(filepath);//不存在就采用捕获capture,存在就采用追加appendif (!wimFile.exists()) {WimCapture(params[0].toString() + ":\\", m_BackupFilePath, params[1].toString(), params[2].toString()+"_"+getSystemDrive());}else {WimAppend(params[0].toString() + ":\\", m_BackupFilePath, params[1].toString(), params[2].toString()+"_"+getSystemDrive());}//判断进程结束后,是否已成功完成备份if ((m_DoingOutput.contains("Calculating integrity table for WIM") && m_DoingOutput.contains("(100%) done"))|| (m_DoingOutput.contains("Archiving file data:") && m_DoingOutput.contains("(100%) done"))) {qDebug() << "备份成功完成";emit sigDialogResultThread(1,1);emit sigUpdateBtn(true);return true;}else if(m_DoingOutput.contains("ERROR: Exiting with error code")){qDebug()<< "系统备份失败";emit sigDialogResultThread(1,0);emit sigUpdateBtn(true);return false;}return false;
}void CSystemReloadThread::systemRestore(const QString& backupName, const int& index)
{m_threadParams.clear();m_threadParams.append(backupName);m_threadParams.append(index);m_memberFun = &CSystemReloadThread::systemRestore;this->start();
}bool CSystemReloadThread::systemRestore(QVariantList params)
{//winPE的系统盘可能和windows10下不同,因此此处需要从备份文件的描述中获取系统盘//使用wimlib-imagex的info命令检验QString cmd = QString("\"%1/SystemReload/wimlib-imagex.exe\" info \"%2\"").arg(QDir::currentPath()).arg(params[0].toString());QProcess process;process.start(cmd);process.waitForFinished();QByteArray all = process.readAll();QString strall = QString(all);QString systemDrive;if (!strall.contains("Available Images:")) {qDebug() << "此wim无效,无法进行还原";}else {qDebug() << "有可用的Images";int pos = strall.indexOf("Description:");strall = strall.mid(pos);pos = strall.indexOf("\r\n");systemDrive = strall.mid(pos - 1, 1);}//在winPE环境中,先格式化系统盘if(FormatVolume(systemDrive, "NTFS")){qDebug()<< "格式化成功";}else{qDebug()<< "格式化失败";emit sigDialogResultThread(2,0);emit sigUpdateBtn(true);return false;}//将wim文件应用到系统盘WimApply(params[0].toString(), params[1].toInt(), systemDrive+":\\");if (m_DoingOutput.contains("Done applying WIM image") || (m_DoingOutput.contains("Applying metadata to files") && m_DoingOutput.contains("(100%) done"))) {qDebug() << "还原成功完成";emit sigDialogResultThread(2,1);emit sigUpdateBtn(true);return true;}else if(m_DoingOutput.contains("ERROR: Exiting with error code")){qDebug()<< "系统还原失败";emit sigDialogResultThread(2,0);emit sigUpdateBtn(true);return false;}return false;
}void CSystemReloadThread::systemPEDownload()
{m_threadParams.clear();m_memberFun = &CSystemReloadThread::systemPEDownload;this->start();
}bool CSystemReloadThread::systemPEDownload(QVariantList params)
{emit sigDialogResultThread(3,0);//创建下载文件夹QDir tempDir(m_DownloadFilePath);if (!tempDir.exists()) {if (!tempDir.mkpath(m_DownloadFilePath)) {qDebug() << "failed to create downDir";return false;}}//下载文件m_DownloadFlag = true;downloadFile(m_DownloadMd5, m_DownloadUrl, m_DownloadFilePath, "");if (!m_DownloadFlag) {qDebug() << "download error";emit sigDialogResultThread(3,1);return false;}//解压文件std::string strDownloadInfo = m_DownloadFilePath.toStdString() + "winPE_X64_local.zip";std::string strTempDirPath = m_DownloadFilePath.toStdString();unZip(strDownloadInfo.c_str(), strTempDirPath.c_str());DeleteFileA(strDownloadInfo.c_str());//本地模式,使用bcdedit.exe 编辑BCD引导文件,进行winPE的菜单添加QString systemDrive = getSystemDrive();QString cmd = QString("bcdedit /create {%1} /d %2 /device && ""bcdedit /create  {%3} /d %4 /application osloader && ""bcdedit /set {%5} ramdisksdidevice partition=%6: && ""bcdedit /set {%7} ramdisksdipath %8 && ""bcdedit /set {%9} device ramdisk=[%10:]%11,{%12} && ""bcdedit /set {%13} description %14 && ""bcdedit /set {%15} locale zh-CN && ""bcdedit /set {%16} inherit {bootloadersettings} && ""bcdedit /set {%17} osdevice ramdisk=[%18:]%19,{%20} && ""bcdedit /set {%21} systemroot \\windows && ""bcdedit /set {%22} detecthal Yes && ""bcdedit /set {%23} winpe Yes && ""bcdedit /set {%24} ems no && ""bcdedit /displayorder {%25} /addlast && ""bcdedit /timeout %26 && ""bcdedit /default {%27}").arg(LOCAL_WINPE_DEVICE_GUID).arg(LOCAL_WINPE_DISPNAME).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_DISPNAME).arg(LOCAL_WINPE_DEVICE_GUID).arg(systemDrive).arg(LOCAL_WINPE_DEVICE_GUID).arg(LOCAL_WINPE_BOOT_SDI).arg(LOCAL_WINPE_OSLOADER_GUID).arg(systemDrive).arg(LOCAL_WINPE_BOOT_WIM).arg(LOCAL_WINPE_DEVICE_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_DISPNAME).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(systemDrive).arg(LOCAL_WINPE_BOOT_WIM).arg(LOCAL_WINPE_DEVICE_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(LOCAL_WINPE_OSLOADER_GUID).arg(10).arg(LOCAL_WINPE_OSLOADER_GUID);QStringList args;args << "/C" << cmd;QString program = "cmd.exe";QProcess process;process.start(program, args);process.waitForFinished();//移动到系统盘指定文件夹QString i4path = systemDrive + ":/i4";QDir i4Dir(i4path);if (!i4Dir.exists()) {if (!i4Dir.mkpath(i4path))qDebug() << "failed to create dir";}QString i4sourcepath = QDir::currentPath() + "/SystemBackup/temp/winPE_X64_local";CopyDir(i4sourcepath, i4path);//删除文件夹QDir(i4sourcepath).removeRecursively();emit sigDialogResultThread(3,2);return false;
}//将某个盘捕获到指定目录,生成wim文件
//WimCapture("c:\\", "e:\\", "c_bak", "c盘备份");
void CSystemReloadThread::WimCapture(const QString& sourcePath, const QString& targetPath, const QString& backupName, const QString& backupDescription)
{//wimlib-imagex capture C:\ D:\C_Bak.wim C_bak C盘备份 --check --snapshotQString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" capture %2 \"%3\" \"%4\" \"%5\" --compress=XPRESS --threads=4 --snapshot")//QString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" capture %2 \"%3\" \"%4\" \"%5\" --check --snapshot").arg(QDir::currentPath()).arg(sourcePath).arg(targetPath + backupName +".wim").arg(backupName).arg(backupDescription);runCMD(commandLine.toStdString());
}//追加到某个wim文件
//WimAppend("c:\\", "e:\\", "c_bak", "c盘备份");
void CSystemReloadThread::WimAppend(const QString& sourcePath, const QString& targetPath, const QString& backupName, const QString& backupDescription)
{//wimlib-imagex append c:\ d:\c_bak.wim c_bak_2 c盘备份//追加的话,参数%4(备份名字(不是备份文件))不能和之前相同QString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" append %2 \"%3\" \"%4\" \"%5\" --compress=XPRESS --threads=4 --snapshot")//QString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" append %2 \"%3\" \"%4\" \"%5\" --check --snapshot").arg(QDir::currentPath()).arg(sourcePath).arg(targetPath + backupName + ".wim").arg(backupName +"_"+ QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(backupDescription);runCMD(commandLine.toStdString());
}//将wim文件应用到某个盘
//WimApply("e:\\c_bak.wim", 1, "c:\\");
void CSystemReloadThread::WimApply(const QString& backupPath, const int& index, const QString& targetPath)
{//wimlib-imagex apply d:\c_bak.wim 1 c:\
QString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" apply \"%2\" %3 %4").arg(QDir::currentPath()).arg(backupPath).arg(index).arg(targetPath);runCMD(commandLine.toStdString());
}//检查wim文件信息
//WimInfo("e:\\c_bak.wim");
void CSystemReloadThread::WimInfo(const QString& backupPath)
{//wimlib-imagex info d:\c_bak.wimQString commandLine = QString("\"%1/SystemReload/wimlib-imagex.exe\" info \"%2\"").arg(QDir::currentPath()).arg(backupPath);runCommandLine(commandLine);
}//获取当前系统盘盘符
QString CSystemReloadThread::getSystemDrive()
{char str[MAX_PATH]{0};GetSystemDirectoryA(str, MAX_PATH);return QString::fromStdString(std::string(1, str[0]));
}//磁盘格式化(需要在winPE执行)
//参数:盘符(c) 、 文件系统(ntfs)
bool CSystemReloadThread::FormatVolume(QString drive, QString format)
{QString program = "cmd.exe";QStringList arguments;arguments << "/c" << "format " + drive + ": /FS:" + format + " /Q /Y";QProcess p;p.start(program, arguments);if (p.waitForStarted()){p.waitForFinished();qDebug() << "成功";return true;}else{qDebug() << "失败";return false;}return 0;
}//通过命令行执行外部程序
int CSystemReloadThread::runCMD(std::string cmd)
{HANDLE hPipeRead, hPipeWrite;SECURITY_ATTRIBUTES saAttr;STARTUPINFOA siStartInfo;DWORD dwRead;CHAR chBuf[4096];// 创建匿名管道saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);saAttr.bInheritHandle = TRUE;saAttr.lpSecurityDescriptor = NULL;if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0)){return 1;}// 为子进程设置文件句柄SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, 0);// 初始化 STARTUPINFOA 结构体ZeroMemory(&siStartInfo, sizeof(STARTUPINFOA));siStartInfo.cb = sizeof(STARTUPINFOA);siStartInfo.hStdOutput = hPipeWrite;siStartInfo.hStdError = hPipeWrite;siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;// 启动外部程序if (!CreateProcessA(NULL, (LPSTR)cmd.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo)){return 1;}// 关闭管道的写入端,这样在读取管道时可以知道进程已结束CloseHandle(hPipeWrite);// 循环读取管道中的输出信息while (ReadFile(hPipeRead, chBuf, sizeof(chBuf), &dwRead, NULL) && dwRead > 0){// 在这里对 chBuf 中的输出信息进行处理// 例如输出到控制台m_DoingOutput = QString::fromStdString(ANSItoUTF8(chBuf));emit sigUpdateDoingText(m_DoingOutput);//        QFile logfile(QDir::currentPath()+ "/SystemBackup/test.log");
//        logfile.open(QIODevice::ReadWrite|QIODevice::Text|QIODevice::Append);
//        QDataStream out(&logfile);
//        out<< m_DoingOutput <<"\r\n";
//        logfile.close();}// 等待子进程结束WaitForSingleObject(piProcInfo.hProcess, INFINITE);// 关闭句柄CloseHandle(piProcInfo.hProcess);CloseHandle(piProcInfo.hThread);CloseHandle(hPipeRead);return 0;
}//关闭正在执行的外部程序
void CSystemReloadThread::killProcess()
{if(piProcInfo.hProcess){TerminateProcess(piProcInfo.hProcess,0);CloseHandle(piProcInfo.hProcess);CloseHandle(piProcInfo.hThread);}
}//下载文件
bool CSystemReloadThread::downloadFile(QString md5, const QString& downloadUrl, const QString& downloadDirPath, const QString& filename)
{//请求链接QStringList list = downloadUrl.split("/");QString filename2 = list.at(list.size() - 1);if (filename.length() > 0)filename2 = "/" + filename;//存放文件夹QString downloadDir(downloadDirPath);QDir dir(downloadDir);if (!dir.exists()) {if (!dir.mkpath(downloadDir))qDebug() << "failed to create dir";}//打开目标文件,先open,便于后续分块写入QString downloadName(downloadDir + filename2);QFile downloadFile(downloadName);if (!downloadFile.open(QIODevice::ReadWrite)) {qDebug() << "open downloadFile error";return false;}//发送HTTP-Get请求QEventLoop* loop = new QEventLoop;QNetworkAccessManager* manager = new QNetworkAccessManager(this);QNetworkRequest request;request.setUrl(QUrl(downloadUrl));QNetworkReply* reply = manager->get(request);if (!reply) {qDebug() << "Failed to send request!";return false;}//信号与槽接收响应//分块获取文件信息,并写入文件中QObject::connect(reply, &QNetworkReply::readyRead, this, [&]() {downloadFile.write(reply->readAll());}, Qt::DirectConnection);//定时获取下载进度qint64 curtype = 0;qint64 oldtype = 0;qint64 totaltype = 0;int usetime = 0;QTimer* time = new QTimer(this);time->start(1000);QObject::connect(time, &QTimer::timeout, this, [&] {qint64 speed = curtype - oldtype;oldtype = curtype;usetime++;}, Qt::DirectConnection);//网络请求完成时QObject::connect(reply, &QNetworkReply::finished, this, [&]() {//处理HTTP响应if (reply->error() != QNetworkReply::NoError) {qDebug() << "Error:" << reply->errorString();qDebug() << "download failed!";downloadFile.close();m_DownloadFlag = false;dir.remove(downloadName);}else {downloadFile.write(reply->readAll());downloadFile.close();qDebug() << "download success";//检验文件QFile theFile(downloadName);if (!theFile.open(QIODevice::ReadOnly)) {qDebug() << "open failed";}QCryptographicHash hash(QCryptographicHash::Md5);const qint64 blockSize = 1024 * 1024 * 100;  // 每次读取的块大小QByteArray buffer;while (!theFile.atEnd()) {buffer = theFile.read(blockSize);hash.addData(buffer);}QByteArray md5file = hash.result();theFile.close();if (md5file.toHex().constData() != md5.toLower()) {m_DownloadFlag = false;DeleteFileA(downloadName.toStdString().c_str());}else {}}manager->deleteLater();reply->deleteLater();time->deleteLater();loop->exit();}, Qt::DirectConnection);// 下载进度处理QObject::connect(reply, &QNetworkReply::downloadProgress, [&](qint64 bytesReceived, qint64 bytesTotal) {//qDebug() << "Downloaded" << bytesReceived << "out of" << bytesTotal << "bytes";curtype = bytesReceived;totaltype = bytesTotal;});loop->exec();return m_DownloadFlag;
}//解压压缩包
//传参:压缩包路径、目标文件夹路径
void CSystemReloadThread::unZip(const char* zipName, const char* dirName) {int iErr = 0;struct zip* zipfile = NULL;struct zip_file* entries = NULL;struct zip_stat stat;zip_int64_t i64Num = 0;zip_int64_t i64Count = 0;int iRead = 0;int iLen = 0;char buf[1024];memset(&stat, 0, sizeof(stat));memset(buf, 0, sizeof(buf));zipfile = zip_open(zipName, ZIP_CHECKCONS, &iErr);if (!zipfile){printf("zip open failed:%d\n", iErr);exit(EXIT_FAILURE);}//get how many entrrites in archivei64Num = zip_get_num_entries(zipfile, 0);for (i64Count = 0; i64Count < i64Num; i64Count++){iLen = 0;if (zip_stat_index(zipfile, i64Count, 0, &stat) == 0){printf("the file name is:%s\n", stat.name);}entries = zip_fopen_index(zipfile, i64Count, 0);if (!entries){printf("fopen index failed\n");goto End;}//create the original filechar filePath[MAX_PATH]{ 0 };strcpy(filePath, dirName);strcat(filePath, "/");strcat(filePath, stat.name);if (filePath[strlen(filePath) - 1] == '/') {QDir tempDir(filePath);if (!tempDir.exists()) {if (!tempDir.mkdir(filePath))qDebug() << "failed to create dir";}zip_fclose(entries);continue;}FILE* fp = fopen(filePath, "wb+");if (!fp){printf("create local file failed\n");zip_fclose(entries);goto End;}while (iLen < stat.size){iRead = zip_fread(entries, buf, 1024);if (iRead < 0){printf("read file failed\n");fclose(fp);zip_fclose(entries);goto End;}fwrite(buf, 1, iRead, fp);iLen += iRead;}zip_fclose(entries);fclose(fp);}End:zip_close(zipfile);
}//拷贝文件夹
//CopyDir("e:\\zyh","f:\\zyh");
bool CSystemReloadThread::CopyDir(const QString& fromDir, const QString& toDir)
{QDir sourceDir(fromDir);QDir targetDir(toDir);if (!targetDir.exists()) {    /**< 如果目标目录不存在,则进行创建 */if (!targetDir.mkpath(targetDir.absolutePath())) {qDebug() << targetDir.absolutePath();return false;}}QFileInfoList fileInfoList = sourceDir.entryInfoList();foreach(QFileInfo fileInfo, fileInfoList) {if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")continue;if (fileInfo.isDir()) {    /**< 当为目录时,递归的进行copy */if (!CopyDir(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName())))return false;}else {            /**< 当允许覆盖操作时,将旧文件进行删除操作 */if (targetDir.exists(fileInfo.fileName())) {targetDir.remove(fileInfo.fileName());}/// 进行文件copyif (!QFile::copy(fileInfo.filePath(), targetDir.filePath(fileInfo.fileName()))) {return false;}else {qDebug() << "copy file" << fileInfo.filePath() << "success";}}}return true;
}

本次主要利用该工具做系统备份和还原,经研究发现,极客狗装机和老毛桃之类的第三方系统操作软件,调用的其实也是wimlib-imagex.exe,因此进行参考,但是发现利用其备份系统时,有时候遇到某些文件会导出备份出错,暂不清楚原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/198479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】资源配额及私有镜像仓库

资源配额及私有镜像仓库 一、Docker资源配额1.1、控制cpu1.1.1、cpu份额控制1.1.2、core核心控制1.1.3、配额控制参数的混合使用 1.2、控制内存1.3、控制IO1.4、资源释放 二、Docker私有镜像仓库Harbor2.1、Harbor简介2.2、为Harbor自签发证书【1】生成ca证书【2】生成域名的证…

输出完全二叉树中某个结点的双亲和所有子孙。假设完全二叉树的顺序存储在一维数组A[n]中。

思路&#xff1a; 首先定义两个函数&#xff0c;getParent函数用于获取指定结点的双亲结点的索引&#xff0c;printDescendants函数用于输出指定结点的所有子孙。然后在main函数中&#xff0c;创建表示完全二叉树的数组A&#xff0c;并针对指定结点索引进行相关操作&#xf…

HOST文件被挟持,无法上网,如何解决。

问题&#xff1a; 晚上开机&#xff0c;突然发现无法联网&#xff0c;提示网络异常 解决&#xff1a; 首先网络诊断&#xff0c;host文件被劫持&#xff0c;修复后&#xff0c;仍然不行。 然后测试手机热点&#xff0c;发现仍然无法联网 尝试用火绒修复&#xff0c;无果。 所有…

Python 解析JSON实现主机管理

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;它以易于阅读和编写的文本形式表示数据。JSON 是一种独立于编程语言的数据格式&#xff0c;因此在不同的编程语言中都有对应的解析器和生成器。JSON 格式的设计目标是易于理解、…

【解决方案】环保设备用电与电网数据集中展示平台的应用与研究

摘 要&#xff1a;近年来&#xff0c;信息化不断推进&#xff0c;政府工作方式以及职能不断改革&#xff0c;许多省级环保部门开展环保与信息技术的融合&#xff0c;用于推进环保的发展。本文基于环境监测研究省级环保与电网数据集中展示平台的应用。环境监测是环保工作的重要组…

读书笔记-《数据结构与算法》-摘要1[数据结构]

文章目录 [数据结构]1. String - 字符串2. Linked List - 链表2.1 链表的基本操作2.1.1 反转链表单向链表双向链表 2.1.2 删除链表中的某个节点2.1.3 链表指针的鲁棒性2.1.4 快慢指针 3. Binary Tree - 二叉树3.1 树的遍历3.2 Binary Search Tree - 二叉查找树 4. Queue - 队列…

JSP入门+EL表达式+JSTL标签

1.JSP&#xff1a; 1.指令 2.注释 3.内置对象 2.MVC开发模式 3.EL表达式 4.JSTL标签 5.三层架构 ## JSP&#xff1a; 1.指令 *用于配置JSP页面&#xff0c;导入资源文件 *格式&#xff1a;<% 指令名称 属性名1属性值1 属性名2属性值2 .......%> *分类&#xff1…

格雷希尔帮助仪器仪表测试时快速密封的G60C系列接头其优势有哪些

仪器仪表在工业领域中扮演着重要的角色&#xff0c;如&#xff1a;压力表&#xff0c;压力传感器、压力变送器、压力开关、压力歧管等这些&#xff0c;在工业领域中都是随处可见的&#xff0c;其数据的精度直接影响着产品在生产过程中的质量和安全性&#xff1b;因此&#xff0…

食品行业研究:金枪鱼产业发展及市场消费分析

金枪鱼是无污染、高档、美味、安全、健康的绿色海洋动物食品&#xff0c;是国际营养协会推荐的世界三大营养鱼种之一 ,它凭借较高的经济价值、较广的分布范围、丰富的资源储量等优势&#xff0c;成为当今世界远洋渔业发展的关注重点和国际水产品贸易的主要鱼种。 金枪鱼类是高度…

3分钟,全方面了解透明oled拼接屏

透明OLED拼接屏是一种先进的显示技术&#xff0c;它具有透明度高、色彩鲜艳、轻薄柔韧、拼接灵活、功耗低、寿命长等特点。在商业、教育、展示、娱乐等领域&#xff0c;透明OLED拼接屏的应用越来越广泛。 在商业领域&#xff0c;透明OLED拼接屏可以作为商品展示柜&#xff0c;通…

系统运维工具KSysAK——让运维回归简单

系统运维工具KSysAK——让运维回归简单 1.基本信息 1.1概述 系统异常定位分析工具KSysAK是云峦操作系统研发及运维人员总结开发及运维经验&#xff0c;设计和研发的多个运维工具的集合&#xff0c;可以覆盖系统的日常监控、线上问题诊断和系统故障修复等常见运维场景。 工具…

从一个bug认识 Spring 单例模式

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」 谁还没在 Spring 里栽过跟头呢&#xff0c;从哪儿跌倒&#xff0c;就从哪儿睡一会儿&#xff0c;然后再爬起来。 讲点儿武德 这是由一个真实的 bug 引起的&#xff0c;bug 产生的原因就是忽略了 Spring Bean 的…

网络层之无分类编址CIDR(内涵计算例题)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

初学vue3与ts:element-plus的警告(Extraneous non-props attributes (ref_key) ...)

用了vue3与ts&#xff0c;ui我就选了element-plus element-plus官网&#xff1a;https://element-plus.org/zh-CN/ element-plus官网(国内镜像站点)&#xff1a;https://element-plus.gitee.io/zh-CN/ 国内镜像站点如果进不去的话&#xff0c;在element-plus官网最下面的链接-&…

Jupyter Notebook中设置Cell主题

1. 获取本机Jupyter的配置目录 C:\Users\Administrator>jupyter --data-dir C:\Users\Administrator\AppData\Roaming\jupyter2. 进入获取的目录&#xff0c;创建指定路径 C:\Users\Administrator>cd C:\Users\Administrator\AppData\Roaming\jupyter C:\Users\Adminis…

TikTok新闻视角:短视频如何改变信息传递方式?

随着数字时代的不断发展&#xff0c;信息传递的方式也在不断演变。近年来&#xff0c;短视频平台TikTok崭露头角&#xff0c;通过其独特的15秒短视频形式&#xff0c;逐渐在新闻传播领域占据一席之地。本文将深入探讨TikTok在新闻视角下是如何改变信息传递方式的&#xff0c;以…

计算机毕设:基于机器学习的生物医学语音检测识别 附完整代码数据可直接运行

项目视频讲解: 基于机器学习的生物医学语音检测识别 完整代码数据可直接运行_哔哩哔哩_bilibili 运行效果图: 数据展示: 完整代码: #导入python的 numpy matplotlib pandas库 import pandas as pd import numpy as np import matplotlib.pyplot as plt #绘图 import se…

jupyter notebook中添加内核kernel

step1 检查环境中是否有kernel python -m ipykernel --versionstep2 若没有kernel&#xff0c;则需要安装 kernel conda install ipykernel -i https://pypi.tuna.tsinghua.edu.cn/simplestep3 查看已添加的内核 jupyter kernelspec liststep4 添加内核 python -m ipykerne…

学习php中使用composer下载安装firebase/php-jwt 以及调用方法

学习php中使用composer下载安装firebase/php-jwt 以及调用方法 1、安装firebase/php-jwt2、封装jwt类 1、安装firebase/php-jwt composer require firebase/php-jwt安装好以后出现以下文件: 2、封装jwt类 根据所使用的php框架&#xff0c;在指定目录创建 Token.php <?ph…

外贸建站要国外服务器吗?海外服务器推荐?

外贸建站如何选国外服务器&#xff1f;海洋建站用什么服务器好&#xff1f; 外贸建站已经成为企业拓展国际市场的一项重要举措。然而&#xff0c;一个关键问题摆在许多企业面前&#xff1a;外贸建站是否需要选择国外服务器呢&#xff1f;这个问题涉及到多方面的考虑因素&#…