无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 677|回复: 41
打印 上一主题 下一主题

[原创] 在VHD系统下,实现每次重启都还原到最佳初始状态的完美方案

  [复制链接]
跳转到指定楼层
1#
发表于 昨天 12:50 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
本帖最后由 D_M_GuYing 于 2025-10-11 20:55 编辑

调整了操作顺序:先完成差分文件的创建,确认成功后再修改启动引导配置。这样可以避免在差分文件创建失败的情况下错误修改引导配置
链接: https://yun.139.com/shareweb/#/w/i/2qidDZNHuCya1  
提取码:w3kj  

前题:你要做好了VHD系统到最佳状态,到PE创建了差分,修改启动项用差分启动系统。例如:
父文件:D:\SYS\25H2.VHDX
差分文件:D:\SYS\A.VHDX





执行后,会自动搜索.CMD文件夹下A.VHDX和B.VHDX执行删除操作,如果你的启动项是A.VHDX,因为正在使用中,所以是删除不掉的。然后.CMD建立一个新的差分文件B.VHDX,修改启动项的设备文件为B.VHDX,反之亦然。

就这吗简单!


复制代码,另存为.CMD,放到你的VHDX所在文件夹,修改你的变量
:: 差分子文件变量
set "VHD1=A.vhdx"
set "VHD2=B.vhdx"
:: 父文件变量
set "BASE_VHD=25H2.VHDX"

可删除最后的那个暂停代码pause,创建计划任务,每次系统启动时,执行.cmd。这样就不会每次手动了。--------------------------------------------------------------------------------------------------------------------------------------


@echo off
chcp 65001 >nul 2>&1
setlocal enabledelayedexpansion
cls


:: 差分子文件变量
set "VHD1=A.vhdx"
set "VHD2=B.vhdx"
:: 父文件变量
set "BASE_VHD=25H2.VHDX"  


:: 强制删除A.vhdx和B.vhdx(无论是否存在)
echo 正在清理旧文件...
if exist "!VHD1!" (
    del /f /q "!VHD1!" >nul 2>&1
    if not exist "!VHD1!" (echo ✅ 已删除 !VHD1!) else (echo ⚠️ 无法删除 !VHD1!,可能被占用)
)
if exist "!VHD2!" (
    del /f /q "!VHD2!" >nul 2>&1
    if not exist "!VHD2!" (echo ✅ 已删除 !VHD2!) else (echo ⚠️ 无法删除 !VHD2!,可能被占用)
)
echo.


:: 1. 获取当前目录
pushd %~dp0 & cd /d "%~dp0"
set "CUR_DIR=%cd%"
echo Current folder: %CUR_DIR%
echo VHD files to switch: %VHD1% ↔ %VHD2%


:: 2. 提取盘符和路径
set "DRIVE=%CUR_DIR:~0,2%"
set "REL_PATH=%CUR_DIR:~2%"


:: 3. 自动搜索VHD启动项ID
echo.
echo 正在自动搜索VHD启动项ID...
set "VHDX_ID="
set "in_vhd_entry=0"


:: 遍历bcdedit输出,提取包含"vhd"的启动项ID
for /f "tokens=1,* delims=:" %%a in ('bcdedit /enum /v 2^>nul') do (
    :: 清理行首空格和特殊字符
    set "line=%%a%%b"
    set "line=!line: =!"
   
    :: 检测到标识符行,提取ID
    if "!line:~0,10!"=="identifier" (
        set "current_id=!line:identifier=!"
        set "current_id=!current_id:{=!"  :: 移除左大括号
        set "current_id=!current_id:}=!"  :: 移除右大括号
        set "current_id=!current_id:"=!"  :: 移除引号
        set "in_vhd_entry=0"  :: 重置标记
    )
   
    :: 检测到包含"vhd"的行,标记为VHD启动项
    echo "!line!" | findstr /i "vhd" >nul 2>&1
    if !errorlevel! equ 0 (
        set "in_vhd_entry=1"
    )
   
    :: 若在VHD启动项中且已获取ID,则确定为目标ID
    if !in_vhd_entry! equ 1 if defined current_id (
        set "VHDX_ID={!current_id!}"
        goto :found_vhd_id  :: 找到后退出循环
    )
)
:found_vhd_id


:: 验证ID是否存在
if "!VHDX_ID!"=="" (
    echo ❌ 错误:未找到VHD类型的启动项,请检查系统配置
    pause
    exit /b 1
)
echo ✅ 找到VHD启动项ID:!VHDX_ID!


:: 4. 构建路径
set "SUFFIX_DEVICE=,locate=custom:12000002"
set "SUFFIX_OSDEVICE=,locate=custom:22000002"
set "VHD1_DEV=vhd=[%DRIVE%]%REL_PATH%\%VHD1%%SUFFIX_DEVICE%"
set "VHD1_OS=vhd=[%DRIVE%]%REL_PATH%\%VHD1%%SUFFIX_OSDEVICE%"
set "VHD2_DEV=vhd=[%DRIVE%]%REL_PATH%\%VHD2%%SUFFIX_DEVICE%"
set "VHD2_OS=vhd=[%DRIVE%]%REL_PATH%\%VHD2%%SUFFIX_OSDEVICE%"


:: 5. 检测文件存在性(清理后应该都不存在)
set "VHD1_EXIST=0"
set "VHD2_EXIST=0"
if exist "%CUR_DIR%\%VHD1%" set "VHD1_EXIST=1"
if exist "%CUR_DIR%\%VHD2%" set "VHD2_EXIST=1"


:: 6. 显示检测结果
echo.
echo ==============================================
echo  File Detection:
if %VHD1_EXIST% equ 1 (echo ✅ %VHD1% exists) else (echo ❌ %VHD1% not found)
if %VHD2_EXIST% equ 1 (echo ✅ %VHD2% exists) else (echo ❌ %VHD2% not found)
echo ==============================================


:: 7. 确定目标差分文件
set "TARGET="
set "NEW_DEV="
set "NEW_OS="


if %VHD1_EXIST% equ 1 (
    set "TARGET=%VHD2%"
    set "NEW_DEV=%VHD2_DEV%"
    set "NEW_OS=%VHD2_OS%"
) else if %VHD2_EXIST% equ 1 (
    set "TARGET=%VHD1%"
    set "NEW_DEV=%VHD1_DEV%"
    set "NEW_OS=%VHD1_OS%"
) else (
    :: 当A和B都不存在时,默认使用A.vhdx
    set "TARGET=%VHD1%"
    set "NEW_DEV=%VHD1_DEV%"
    set "NEW_OS=%VHD1_OS%"
    echo 提示:所有文件均不存在,默认切换目标为 %TARGET%
)


:: 8. 先执行差分文件创建任务
echo.
echo ==============================================
echo 子文件创建任务:
echo  母文件:%BASE_VHD%
echo  子文件:%TARGET%(与启动目标一致)
echo  目标路径:%CUR_DIR%
echo ==============================================


set "CREATE_SUCCESS=0"
:: 检查母文件是否存在
if not exist "%CUR_DIR%\%BASE_VHD%" (
    echo ❌ 错误:母文件 %BASE_VHD% 未在 %CUR_DIR% 找到,无法创建子文件
) else (
    echo ⚠️  正在创建差分文件(需管理员权限)...
    (
        echo create vdisk file="%CUR_DIR%\%TARGET%" parent="%CUR_DIR%\%BASE_VHD%"
        echo exit
    ) | diskpart
   
    :: 验证差分文件创建结果
    if exist "%CUR_DIR%\%TARGET%" (
        echo ✅ 成功:差分文件 %TARGET% 已创建 → %CUR_DIR%\%TARGET%
        set "CREATE_SUCCESS=1"
    ) else (
        echo ❌ 失败:差分文件未创建,请检查权限和母文件完整性
    )
)
echo ==============================================


:: 9. 只有差分文件创建成功后,才执行引导切换
if %CREATE_SUCCESS% equ 1 (
    echo.
    echo Auto-switching to %TARGET%...
    bcdedit /enum %VHDX_ID% >nul 2>&1
    timeout /t 1 /nobreak >nul


    bcdedit /set %VHDX_ID% device "%NEW_DEV%" >nul
    bcdedit /set %VHDX_ID% osdevice "%NEW_OS%" >nul
    bcdedit /enum %VHDX_ID% >nul 2>&1
    timeout /t 1 /nobreak >nul


    :: 验证引导切换结果
    set "FINAL_DEV="
    for /f "tokens=2,*" %%a in ('bcdedit /enum %VHDX_ID% /v ^| findstr /i "device "') do set "FINAL_DEV=%%b"


    echo.
    echo ==============================================
    echo Switch Completed! Target: %CUR_DIR%\%TARGET%
    echo Final Path: %FINAL_DEV%
    echo ==============================================
    if "%FINAL_DEV%"=="%NEW_DEV%" (
        echo ✅ Success: Path is correct
    ) else (
        echo ⚠️  Success: Actual path set to %NEW_DEV%
    )
) else (
    echo.
    echo ⚠️  差分文件创建失败,未修改启动引导配置
)


echo.
echo 按任意键退出...
set /p=
endlocal



评分

参与人数 2无忧币 +10 收起 理由
d9o + 5 赞一个!
lemonle79 + 5 很给力!

查看全部评分

42#
发表于 1 小时前 | 只看该作者
感谢分享
回复

使用道具 举报

41#
发表于 昨天 23:49 | 只看该作者
感谢分享 !
回复

使用道具 举报

40#
发表于 昨天 22:41 | 只看该作者
本帖最后由 baby1277 于 2025-10-11 23:26 编辑

vhd还原研究了半年,分享下我的方法。

安装阶段:
1:差分 a.vhdx  b.vhdx  back.vhdx
echo create vdisk file=%~dp0back.vhdx parent=%~dp0Win11.vhdx|diskpart
copy /y back.vhdx b.vhdx
copy /y back.vhdx a.vhdx

2:创建 引导a.vhdx的bcd文件: a_bcd   (挂载vhd后用bcdboot创建引导菜单 再用bcdedit /export导出)
3:创建 引导a.vhdx的bcd文件: b_bcd

开机运行阶段:
用back.vhdx 覆盖a.vhdx和b.vhdx  复制成功则导入对应的bcd文件来改变vhd文件路径

cd /d %~dp0
copy /y back.vhdx a.vhdx && bcdedit /import "%cd%\a_bcd"
copy /y back.vhdx b.vhdx && bcdedit /import "%cd%\b_bcd"



以上开机脚本只能用于比较固定的引导菜单,但也可以变通些。
读取bcd文件的guid 用 bcdedit  /default 来改变vhd文件路径
这时bcd文件仅仅是存储guid和vhd文件路径,不导入就不会影响前期添加的引导菜单。

cd /d %~dp0
copy /y back.vhdx a.vhdx && for /f "tokens=2" %%i in ('bcdedit /store "%cd%\a_bcd" /enum {default} /v^|find /i "resumeobject"') do bcdedit  /default %%i
copy /y back.vhdx b.vhdx && for /f "tokens=2" %%i in ('bcdedit /store "%cd%\b_bcd" /enum {default} /v^|find /i "resumeobject"') do bcdedit  /default %%i

就这么简单,不需要复杂的逻辑,两三句脚本搞定。

回复

使用道具 举报

39#
 楼主| 发表于 昨天 21:56 | 只看该作者
jlshnlhj 发表于 2025-10-11 21:13
父:A.vhdx差分出3个:a.vhdx,b.vhdx,bak.vhdx,每个4M左右。
父vhdx里建批处理开机运行:
copy bak.vh ...

什么事儿都是有变数的,你把第二变就给固定了,这个思维逻辑要不得
回复

使用道具 举报

38#
 楼主| 发表于 昨天 21:45 | 只看该作者
jlshnlhj 发表于 2025-10-11 21:13
父:A.vhdx差分出3个:a.vhdx,b.vhdx,bak.vhdx,每个4M左右。
父vhdx里建批处理开机运行:
copy bak.vh ...

就说咱俩就不在一个路上,别再论了,你的方法,早就有。我只是在从另一个角度在实现同一个目的,我的目的就是要每次开机重启就恢复原位。那你弄那么多a.vhdx,b.vhdx,bak.vhdx,建立N个启动项是不是就没意义了?我的目的就是无论是谁,无论你的VHDX在哪里,你文件名是什么,尽可能的,排除所有外在因素,只要达到前题条件,就可以实现目的。还有,你玩来玩儿去的,搞不好哪次你的b.vhdx,bak.vhdx就失效了,因为你母文件早就修改了,你的b.vhdx,bak.vhdx是2000年创建的....再说,你的b.vhdx,bak.vhdx还不是以父文件为根本作的,你浪费那到几毫秒从根本上重作一个差分,总比用旧的要好,,
回复

使用道具 举报

37#
发表于 昨天 21:13 | 只看该作者
本帖最后由 jlshnlhj 于 2025-10-11 21:15 编辑

父:A.vhdx差分出3个:a.vhdx,b.vhdx,bak.vhdx,每个4M左右。
父vhdx里建批处理开机运行:
copy bak.vhdx a.vhdx
copy bak.vhdx b.vhdx
bcd建3个启动项:a.vhdx,b.vhdx,A.vhdx(升级维护用)
这样可以交替恢复,先用a.vhdx,故障后重启,进b.vhdx,开机成功后自动执行:copy bak.vhdx a.vhdx,此时a.vhdx已恢复。以后一直b.vhdx,故障后再重启,进a.vhdx,开机成功后a.vhdx恢复。


点评

什么事儿都是有变数的,你把第二变就给固定了,这个思维逻辑要不得  详情 回复 发表于 昨天 21:56
就说咱俩就不在一个路上,别再论了,你的方法,早就有。我只是在从另一个角度在实现同一个目的,我的目的就是要每次开机重启就恢复原位。那你弄那么多a.vhdx,b.vhdx,bak.vhdx,建立N个启动项是不是就没意义了?我  详情 回复 发表于 昨天 21:45
回复

使用道具 举报

36#
发表于 昨天 21:03 来自手机 | 只看该作者
谢谢分享
回复

使用道具 举报

35#
 楼主| 发表于 昨天 21:00 | 只看该作者
1801403 发表于 2025-10-11 18:08
楼主能把你的批处理上传吗?你贴出来的批处理,有部份变成表情了。

链接: https://yun.139.com/shareweb/#/w/i/2qidDZNHuCya1  
提取码:w3kj  
回复

使用道具 举报

34#
 楼主| 发表于 昨天 20:55 | 只看该作者
2013ertert 发表于 2025-10-11 20:44
感谢分享,能网盘分享一下吗?谢谢!

链接: https://yun.139.com/shareweb/#/w/i/2qidDZNHuCya1  
提取码:w3kj  
回复

使用道具 举报

33#
 楼主| 发表于 昨天 20:45 | 只看该作者
casttt 发表于 2025-10-11 20:37
现在很少用VHD了,因为象snapshot这样的恢复软件极快,一点就恢复了,所以懒得搞其它的了,

象虚拟机更 ...

这个因人而异,我手贱,总是想尝新,VHD系统适合我
回复

使用道具 举报

32#
发表于 昨天 20:44 | 只看该作者
感谢分享,能网盘分享一下吗?谢谢!

点评

链接: https://yun.139.com/shareweb/#/w/i/2qidDZNHuCya1 提取码:w3kj  详情 回复 发表于 昨天 20:55
回复

使用道具 举报

31#
 楼主| 发表于 昨天 20:39 | 只看该作者
szwp 发表于 2025-10-11 20:17
俺的id不管是legay还是uefi都是相同,切换启动用的相同id,现在手机不方便多打,可以创建一个全A的guid给a. ...

你说复制就可以,用A.VHDX启动后你怎么复制,你复制的是初始吗?你说的复制就可以,那是不是最城码你创建子文件时,就要复制一个改个文件名才可以?那这个文件要是丢了呢,这个文件的基础就是从母文件建立了,那你直接从母文件建立就可以,为什么要脱了裤子放屁?
回复

使用道具 举报

30#
发表于 昨天 20:37 | 只看该作者
现在很少用VHD了,因为象snapshot这样的恢复软件极快,一点就恢复了,所以懒得搞其它的了,

象虚拟机更不用了,因为如与硬件相关就不行了,不过移动硬盘上的WTG还是用VHD的,有他的好处,

不过还是要支持的,各种方案下总有进步,总会有更适用的选择,

点评

这个因人而异,我手贱,总是想尝新,VHD系统适合我  详情 回复 发表于 昨天 20:45
回复

使用道具 举报

29#
 楼主| 发表于 昨天 20:30 | 只看该作者
szwp 发表于 2025-10-11 20:17
俺的id不管是legay还是uefi都是相同,切换启动用的相同id,现在手机不方便多打,可以创建一个全A的guid给a. ...

俺的,俺的,,你以为别人都是俺的?你以为你家ID就不会变了?你以为别人都会自己找ID再复制进去吗?自动重找,找到建立,会排除很多不确定的,这样不好吗,我可以接受不同的声音,但你这种声音太自我弱智,我不接受
回复

使用道具 举报

28#
发表于 昨天 20:25 来自手机 | 只看该作者
没有绝对的可靠,不能保证系统一定会有diskpart和父损坏情况
回复

使用道具 举报

27#
 楼主| 发表于 昨天 20:24 | 只看该作者
1801403 发表于 2025-10-11 18:08
楼主能把你的批处理上传吗?你贴出来的批处理,有部份变成表情了。

惭愧呀,上传不是没成功,.txt,.7z都试了,附件不上去,你说的表情是❌ ⚠️✅?那是有意为之的不是乱码
回复

使用道具 举报

26#
 楼主| 发表于 昨天 20:19 | 只看该作者
szwp 发表于 2025-10-11 19:46
固定bcd guid就不需每次创建,切换就可

全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快,,,快几毫秒?你拷贝的那个正在使用,你怎么拷贝?你拷贝的那个没了呢,你拷贝的那个损坏了,跟父文件不相联呢?从父文件直接重建差分才是正途
回复

使用道具 举报

25#
发表于 昨天 20:17 来自手机 | 只看该作者
俺的id不管是legay还是uefi都是相同,切换启动用的相同id,现在手机不方便多打,可以创建一个全A的guid给a.vhdx 全B的guid给B.vhdx

点评

你说复制就可以,用A.VHDX启动后你怎么复制,你复制的是初始吗?你说的复制就可以,那是不是最城码你创建子文件时,就要复制一个改个文件名才可以?那这个文件要是丢了呢,这个文件的基础就是从母文件建立了,那你直  详情 回复 发表于 昨天 20:39
俺的,俺的,,你以为别人都是俺的?你以为你家ID就不会变了?你以为别人都会自己找ID再复制进去吗?自动重找,找到建立,会排除很多不确定的,这样不好吗,我可以接受不同的声音,但你这种声音太自我弱智,我不接受  详情 回复 发表于 昨天 20:30
回复

使用道具 举报

24#
 楼主| 发表于 昨天 20:14 | 只看该作者
szwp 发表于 2025-10-11 20:05
全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快

差分只需创建一次,如果你没有备份,启动后就已经变了,还不是要回到重建到一步
回复

使用道具 举报

23#
 楼主| 发表于 昨天 20:11 | 只看该作者
szwp 发表于 2025-10-11 20:05
全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快

按实际 ,你说的没错,按严谨,那就顺着来总是没错的,排除一切外在因素的影响,那样不好吗,你就没有过重建立新VHDX重装系统的时候吗,那时,ID是不是变了,,你行,那你弄个通用的出来我学习下好不
回复

使用道具 举报

22#
发表于 昨天 20:08 来自手机 | 只看该作者
初始化时创建ida idb项和差分,以后只需copy成功即设置默认
回复

使用道具 举报

21#
发表于 昨天 20:05 来自手机 | 只看该作者
D_M_GuYing 发表于 2025-10-11 20:00
你的固定了,别人呢?

全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快

点评

差分只需创建一次,如果你没有备份,启动后就已经变了,还不是要回到重建到一步  详情 回复 发表于 昨天 20:14
按实际 ,你说的没错,按严谨,那就顺着来总是没错的,排除一切外在因素的影响,那样不好吗,你就没有过重建立新VHDX重装系统的时候吗,那时,ID是不是变了,,你行,那你弄个通用的出来我学习下好不  详情 回复 发表于 昨天 20:11
回复

使用道具 举报

20#
 楼主| 发表于 昨天 20:00 | 只看该作者
szwp 发表于 2025-10-11 19:46
固定bcd guid就不需每次创建,切换就可

你的固定了,别人呢?

点评

全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快  详情 回复 发表于 昨天 20:05
回复

使用道具 举报

19#
 楼主| 发表于 昨天 19:55 | 只看该作者

这话说到我心里了,就是抛砖引玉,只是提供个想法
回复

使用道具 举报

18#
发表于 昨天 19:50 | 只看该作者
学习一下
回复

使用道具 举报

17#
发表于 昨天 19:46 来自手机 | 只看该作者
固定bcd guid就不需每次创建,切换就可

点评

全球都用同一id不会冲突,差分只需创建一次,后续ab都用拷贝,比diskpart快,,,快几毫秒?你拷贝的那个正在使用,你怎么拷贝?你拷贝的那个没了呢,你拷贝的那个损坏了,跟父文件不相联呢?从父文件直接重建差分才  详情 回复 发表于 昨天 20:19
你的固定了,别人呢?  详情 回复 发表于 昨天 20:00
回复

使用道具 举报

16#
发表于 昨天 19:11 | 只看该作者
谢谢分享!
回复

使用道具 举报

15#
发表于 昨天 18:52 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

14#
发表于 昨天 18:45 | 只看该作者
厉害。收藏先
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-10-12 02:29

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表