|
调用DISM进行系统安装目前
完成功能:映像解析,系统恢复
未完成:引导修复,有思路不知道怎么写 有大佬写出来的吗
引导修复流程如下
----------------------------------(BIOS启动) 则→执行MBR修复⬇
⬆
检测启动方式(UEFI或BIOS) 执行BCD深度配置→→返回修复结果
⬆
------------------------------------(UEFI启动)则→执行UEFI修复 ⬆
个别机器同时兼容(MBR和UEFI启动)这时需要进行检测分区类型(MBR分区是否活动分区或GPT分区检测efi引导分区是否存在如果存 挂载引导分区)
efi引导分区不纯在则根据安装盘符进行取出硬盘所在索引创建efi分区并设置第一分区 修复引导
附上系统安装代码
<火山程序 类型 = "通常" 版本 = 1 />
类 安装系统 <公开 折叠2 @文档 = "category = \"DISM系统恢复\"" @全局类 = 真>
{
方法 DISM镜像解析 <公开 类型 = 文本型 折叠 @禁止流程检查 = 真>
参数 映像路径 <类型 = 文本型>
{
@ WCHAR szCmd[1024] = {0};
@ WCHAR szOutput[65536] = {0};
@ DWORD dwOutputPos = 0;
@ WCHAR* pFinalResult = NULL;
@ BOOL bSuccess = FALSE;
@ INT iCurrentIndex = 0;
@ WCHAR szCurrentName[256] = {0};
@ DOUBLE dCurrentSizeGB = 0.0;
@ BOOL bHasIndex = FALSE;
@ // 构建 DISM 命令
@ _snwprintf_s(szCmd, _countof(szCmd), _TRUNCATE,
@ L"dism /Get-WimInfo /WimFile:\"%s\"",
@ (LPCWSTR)@<映像路径>.GetText());
@ // 创建管道
@ SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
@ HANDLE hReadPipe = NULL, hWritePipe = NULL;
@ if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
@ return L"错误|无法创建管道";
@ }
@ // 设置进程启动信息
@ STARTUPINFOW si = { sizeof(si) };
@ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
@ si.wShowWindow = SW_HIDE;
@ si.hStdOutput = hWritePipe;
@ si.hStdError = hWritePipe;
@ PROCESS_INFORMATION pi = {0};
@ // 启动 DISM 进程
@ if (!CreateProcessW(NULL, szCmd, NULL, NULL, TRUE,
@ CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
@ CloseHandle(hReadPipe);
@ CloseHandle(hWritePipe);
@ return L"错误|无法启动 DISM 进程";
@ }
@ // 读取输出
@ CloseHandle(hWritePipe);
@ CloseHandle(pi.hThread);
@ CHAR szBuffer[4096] = {0};
@ DWORD dwBytesRead = 0;
@ while (ReadFile(hReadPipe, szBuffer, sizeof(szBuffer)-1, &dwBytesRead, NULL) && dwBytesRead > 0) {
@ szBuffer[dwBytesRead] = '\0';
@ INT iConverted = MultiByteToWideChar(CP_ACP, 0, szBuffer, -1,
@ szOutput + dwOutputPos, _countof(szOutput) - dwOutputPos);
@ if (iConverted > 0) {
@ dwOutputPos += iConverted - 1;
@ }
@ }
@ CloseHandle(hReadPipe);
@ WaitForSingleObject(pi.hProcess, INFINITE);
@ CloseHandle(pi.hProcess);
@ // 解析 DISM 输出
@ WCHAR* pLine = szOutput;
@ WCHAR* pEnd = szOutput + wcslen(szOutput);
@ WCHAR szResult[4096] = {0};
@ while (pLine < pEnd) {
@ WCHAR* pLineEnd = pLine;
@ while (*pLineEnd != L'\r' && *pLineEnd != L'\n' && pLineEnd < pEnd) pLineEnd++;
@ WCHAR cSaved = *pLineEnd;
@ *pLineEnd = L'\0';
@ // 解析索引
@ if (wcsstr(pLine, L"索引:") == pLine) {
@ if (bHasIndex) {
@ // 添加分隔符
@ if (wcslen(szResult) > 0) {
@ wcscat_s(szResult, _countof(szResult), L"-");
@ }
@ // 添加条目
@ WCHAR szEntry[512];
@ _snwprintf_s(szEntry, _countof(szEntry), _TRUNCATE,
@ L"%d:%s[%.2fGB]", iCurrentIndex, szCurrentName, dCurrentSizeGB);
@ wcscat_s(szResult, _countof(szResult), szEntry);
@ }
@ iCurrentIndex = _wtoi(pLine + 4);
@ szCurrentName[0] = L'\0';
@ dCurrentSizeGB = 0.0;
@ bHasIndex = TRUE;
@ }
@ // 解析名称
@ else if (wcsstr(pLine, L"名称:") == pLine) {
@ WCHAR* pNameStart = pLine + 4;
@ while (*pNameStart == L' ') pNameStart++;
@ wcscpy_s(szCurrentName, _countof(szCurrentName), pNameStart);
@ }
@ // 解析大小
@ else if (wcsstr(pLine, L"大小:") == pLine) {
@ WCHAR* pSizeStart = pLine + 4;
@ WCHAR szSizeStr[256] = {0};
@ WCHAR* p = szSizeStr;
@ while (*pSizeStart && (p - szSizeStr) < 255) {
@ if (*pSizeStart >= L'0' && *pSizeStart <= L'9') {
@ *p++ = *pSizeStart;
@ }
@ pSizeStart++;
@ }
@ *p = L'\0';
@ if (szSizeStr[0]) {
@ dCurrentSizeGB = _wtoi64(szSizeStr) / 1073741824.0; // 转换为 GB
@ }
@ }
@ *pLineEnd = cSaved;
@ pLine = pLineEnd;
@ while ((*pLine == L'\r' || *pLine == L'\n') && pLine < pEnd) pLine++;
@ }
@ // 添加最后一个镜像
@ if (bHasIndex) {
@ if (wcslen(szResult) > 0) {
@ wcscat_s(szResult, _countof(szResult), L"-");
@ }
@ WCHAR szEntry[512];
@ _snwprintf_s(szEntry, _countof(szEntry), _TRUNCATE,
@ L"%d:%s[%.2fGB]", iCurrentIndex, szCurrentName, dCurrentSizeGB);
@ wcscat_s(szResult, _countof(szResult), szEntry);
@ bSuccess = TRUE;
@ }
@ if (!bSuccess) {
@ return L"错误|未找到有效的镜像信息";
@ }
@ // 返回结果
@ pFinalResult = (WCHAR*)LocalAlloc(LPTR, (wcslen(szResult)+1)*sizeof(WCHAR));
@ wcscpy_s(pFinalResult, wcslen(szResult)+1, szResult);
@ return (LPCWSTR)pFinalResult;
}
方法 DISM安装 <公开 类型 = 文本型 折叠 @禁止流程检查 = 真>
参数 映像路径 <类型 = 文本型>
参数 目标磁盘 <类型 = 文本型>
参数 映像索引 <类型 = 整数>
{
@ // 安全稳定版:修复所有缓冲区溢出问题
@ static volatile LONG progress = 0;
@ static volatile BOOL isRunning = FALSE;
@ static WCHAR status[256] = L"等待开始";
@ static HANDLE hReadPipe = INVALID_HANDLE_VALUE;
@ static HANDLE hProcess = INVALID_HANDLE_VALUE;
@ static CRITICAL_SECTION cs;
@ static BOOL csInitialized = FALSE;
@ static CHAR lastBuffer[4096] = {0};
@ // 安全初始化临界区
@ if (!csInitialized) {
@ InitializeCriticalSection(&cs);
@ csInitialized = TRUE;
@ lastBuffer[0] = '\0';
@ }
@ EnterCriticalSection(&cs);
@ // 安全处理运行中任务
@ if (isRunning) {
@ if (hReadPipe != INVALID_HANDLE_VALUE) {
@ DWORD bytesAvailable = 0;
@ if (PeekNamedPipe(hReadPipe, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable > 0) {
@ CHAR buffer[4096] = {0};
@ DWORD bytesRead = 0;
@
@ if (ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &bytesRead, NULL) && bytesRead > 0) {
@ buffer[bytesRead] = '\0';
@
@ // 安全缓冲区拼接
@ size_t currentLen = strnlen_s(lastBuffer, sizeof(lastBuffer));
@ if (currentLen + bytesRead < sizeof(lastBuffer)) {
@ strcat_s(lastBuffer, sizeof(lastBuffer), buffer);
@ } else {
@ size_t overflow = (currentLen + bytesRead) - sizeof(lastBuffer) + 1;
@ memmove_s(lastBuffer, sizeof(lastBuffer),
@ lastBuffer + overflow,
@ sizeof(lastBuffer) - overflow);
@ strcat_s(lastBuffer, sizeof(lastBuffer), buffer);
@ }
@
@ // 安全解析进度(仅捕获百分比,过滤无关日志)
@ const CHAR* p = lastBuffer;
@ while (*p != '\0') {
@ if (*p == '[') {
@ const CHAR* percentPos = strchr(p, '%');
@ if (percentPos != NULL && (percentPos - p) < 50) {
@ const CHAR* numStart = percentPos - 1;
@ while (numStart > p &&
@ (isdigit(*numStart) || *numStart == '.')) {
@ numStart--;
@ }
@
@ if (numStart < percentPos) {
@ float newProgress = 0.0f;
@ if (sscanf_s(numStart + 1, "%f", &newProgress) == 1) {
@ progress = max(progress, min((int)newProgress, 99));
@ _snwprintf_s(status, _countof(status), _TRUNCATE, L"正在应用映像");
@ }
@ }
@ }
@ }
@ p++;
@ }
@ }
@ }
@ }
@
@ // 安全检查进程状态
@ if (hProcess != INVALID_HANDLE_VALUE) {
@ DWORD exitCode = 0;
@ if (GetExitCodeProcess(hProcess, &exitCode)) {
@ if (exitCode != STILL_ACTIVE) {
@ isRunning = FALSE;
@ progress = (exitCode == 0) ? 100 : 0;
@ _snwprintf_s(status, _countof(status), _TRUNCATE,
@ exitCode == 0 ? L"安装完成" : L"失败(错误码:%d)", exitCode);
@
@ if (hReadPipe != INVALID_HANDLE_VALUE) {
@ CloseHandle(hReadPipe);
@ hReadPipe = INVALID_HANDLE_VALUE;
@ }
@ if (hProcess != INVALID_HANDLE_VALUE) {
@ CloseHandle(hProcess);
@ hProcess = INVALID_HANDLE_VALUE;
@ }
@ }
@ }
@ }
@
@ // 返回格式:"进度|状态"(确保不返回无关日志)
@ WCHAR result[256] = {0};
@ _snwprintf_s(result, _countof(result), _TRUNCATE, L"%d|%s", progress, status);
@ LeaveCriticalSection(&cs);
@ return result;
@ }
@ // 安全启动新任务
@ isRunning = TRUE;
@ progress = 0;
@ lastBuffer[0] = '\0';
@ wcscpy_s(status, _countof(status), L"正在初始化");
@ // 创建安全管道
@ SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
@ HANDLE hWritePipe = INVALID_HANDLE_VALUE;
@ if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 4096)) {
@ isRunning = FALSE;
@ DWORD err = GetLastError();
@ _snwprintf_s(status, _countof(status), _TRUNCATE, L"失败(错误码:%d)", err);
@ WCHAR result[256] = {0};
@ _snwprintf_s(result, _countof(result), _TRUNCATE, L"0|%s", status);
@ LeaveCriticalSection(&cs);
@ return result;
@ }
@ // 安全准备命令
@ WCHAR cmd[1024] = {0};
@ _snwprintf_s(cmd, _countof(cmd), _TRUNCATE,
@ L"DISM /Apply-Image /ImageFile:\"%s\" /Index:%d /ApplyDir:%s",
@ (LPCWSTR)@<映像路径>.GetText(),
@ @<映像索引>,
@ (LPCWSTR)@<目标磁盘>.GetText());
@ // 安全启动进程
@ STARTUPINFOW si = {0};
@ si.cb = sizeof(si);
@ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
@ si.wShowWindow = SW_HIDE;
@ si.hStdOutput = hWritePipe;
@ si.hStdError = hWritePipe;
@ PROCESS_INFORMATION pi = {0};
@ BOOL bSuccess = CreateProcessW(
@ NULL, cmd, NULL, NULL, TRUE,
@ CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
@ NULL, NULL, &si, &pi);
@ // 安全清理
@ if (hWritePipe != INVALID_HANDLE_VALUE) {
@ CloseHandle(hWritePipe);
@ }
@ if (bSuccess) {
@ hProcess = pi.hProcess;
@ CloseHandle(pi.hThread);
@ progress = 5;
@ wcscpy_s(status, _countof(status), L"正在应用映像");
@ } else {
@ DWORD err = GetLastError();
@ isRunning = FALSE;
@ if (hReadPipe != INVALID_HANDLE_VALUE) {
@ CloseHandle(hReadPipe);
@ hReadPipe = INVALID_HANDLE_VALUE;
@ }
@ _snwprintf_s(status, _countof(status), _TRUNCATE, L"失败(错误码:%d)", err);
@ }
@ // 返回格式:"进度|状态"(确保不返回无关日志)
@ WCHAR result[256] = {0};
@ _snwprintf_s(result, _countof(result), _TRUNCATE, L"%d|%s", progress, status);
@ LeaveCriticalSection(&cs);
@ return result;
}
}
|
|