liuzhaoyzz 发表于 2021-1-13 08:02:05

本帖最后由 liuzhaoyzz 于 2021-1-13 08:03 编辑

对于从FAT32分区的bootmgfw.efi直接启动pe.wim的场景:
1、nttwqz的checkbootpart_v4判断错误,指向了ESP分区。
2、dos时代菜鸟判断错误,指向了ESP分区。
3、5大的ChkMbrPbr2021-01-13判断错误,指向了ESP分区。
4、CodeHz的smartmountfirmware判断正确,准确地指向了FAT32分区。

大家可以在虚拟机里面挂几个虚拟硬盘,虚拟硬盘格式MBR、GPT挂两个,操作系统安装在vhd或者直接安装在虚拟硬盘中,应该就能够重现情况了。      

liuzhaoyzz 发表于 2021-1-13 08:16:44

dos时代菜鸟 发表于 2021-1-12 23:16
刚研究了一下 vbs 调用 wmi 实现这个功能,发现了个惊喜,
瞬间 找到并挂载 bcd 启动卷。



你的这段代码,我运行好像出错了。

nttwqz 发表于 2021-1-13 09:42:09

liuzhaoyzz 发表于 2021-1-13 08:02
对于从FAT32分区的bootmgfw.efi直接启动pe.wim的场景:
1、nttwqz的checkbootpart_v4判断错误,指向了ESP ...

已经有高手编程实现了,为何还要用脚本?

liuzhaoyzz 发表于 2021-1-13 09:44:16

nttwqz 发表于 2021-1-13 09:42
已经有高手编程实现了,为何还要用脚本?

哦,我只是反馈下结果,如果能改进最好了。一个需求,有多个解决方案挺好啊。

nttwqz 发表于 2021-1-13 10:17:20

liuzhaoyzz 发表于 2021-1-13 09:44
哦,我只是反馈下结果,如果能改进最好了。一个需求,有多个解决方案挺好啊。

这么看来一个男人/女人难以满足你啊

liuzhaoyzz 发表于 2021-1-13 10:28:03

本帖最后由 liuzhaoyzz 于 2021-1-13 10:39 编辑

nttwqz 发表于 2021-1-13 10:17
这么看来一个男人/女人难以满足你啊
我发起的问题,引来众多高手跟帖,辛苦地写代码,你说说看,如果都不测试、反馈下,这种忽视别人劳动成果的行为,是否是对于辛苦写代码的高手们不尊重?
论坛里面,我怕的就是那种失败了不反馈、成功了不报告,转身就跑路的网友。

dos时代菜鸟 发表于 2021-1-13 11:18:04

本帖最后由 dos时代菜鸟 于 2021-1-13 11:20 编辑

liuzhaoyzz 发表于 2021-1-13 08:16
你的这段代码,我运行好像出错了。




我这边正常呀,正常win10 系统,
估计是你那里 的系统wmi 没有 Win32_Volume,



dos时代菜鸟 发表于 2021-1-13 11:22:02

527104427 发表于 2021-1-13 09:54
我怀疑是NtQuerySystemInformation函数结果不对。因为默认使用的是这个,失败才解析符号链接。
等下有空 ...

wmi 的Win32_Volume 是如何做到的?他用到了 什么 dll 的什么 函数句柄呢?

liuzhaoyzz 发表于 2021-1-13 13:42:12

527104427 发表于 2021-1-13 12:08
麻烦最后测试一下,不行就彻底放弃了。
      这个版本,在另一台电脑上面测试,UEFI下从FAT32分区启动是正常的,但这台电脑没有ESP分区,晚上我回去后再测试下看看。

另外,ChkMbrPbr -DelBootDrv太强制化卸载启动分区了,执行这个命令之后,不管原来启动分区有没有盘符,都直接强制卸载了盘符。应该先检测下原来系统里面有没有给启动分区分配盘符,如果原来有就不要卸载,如果没有才卸载,不然的话可能会导致一定的问题。

liuzhaoyzz 发表于 2021-1-13 13:43:36

dos时代菜鸟 发表于 2021-1-13 11:18
我这边正常呀,正常win10 系统,
估计是你那里 的系统wmi 没有 Win32_Volume,

搞不清楚是怎么回事。也是WIN10。

dos时代菜鸟 发表于 2021-1-13 13:56:57

liuzhaoyzz 发表于 2021-1-13 13:43
搞不清楚是怎么回事。也是WIN10。

管理员权限下运行,那个自动生成的 VBS 如果不能运行,说明WMI 不通用。

liuzhaoyzz 发表于 2021-1-13 13:57:52

dos时代菜鸟 发表于 2021-1-13 13:56
管理员权限下运行,那个自动生成的 VBS 如果不能运行,说明WMI 不通用。

我试了,右击以管理员身份运行也是一样的结果。

liuzhaoyzz 发表于 2021-1-13 14:08:46

本帖最后由 liuzhaoyzz 于 2021-1-13 14:17 编辑

527104427 发表于 2021-1-13 14:04
好像没办法判断哦,因为程序分配跟系统自动分配没区别啊,应该除了系统盘之外,卸载其他盘符不会有啥影响 ...
可能会有影响的。比如说这个引导盘符恰巧是当前系统的我的文档所转移到的盘符,强制卸载这个盘符之后,许多功能就不正常了。(这个场景解释起来比较费劲,但是真的存在,实机测试的)

卸载引导盘符最好能够恢复用户原来的原状,恢复现场。原来有盘符的不要卸载;原来没有盘符的才卸载,这样子比较智能化。


CodeHz 发表于 2021-1-13 14:18:01

liuzhaoyzz 发表于 2021-1-13 14:08
可能会有影响的。比如说这个引导盘符恰巧是当前系统的我的文档所转移到的盘符,强制卸载这个盘符之后,许 ...

(思考了一下,我那个smartmountfirmware好像也会尝试卸载原有的,只不过恰好卸载不掉其他方式挂载的而已(巧合)

liuzhaoyzz 发表于 2021-1-13 14:19:43

CodeHz 发表于 2021-1-13 14:18
(思考了一下,我那个smartmountfirmware好像也会尝试卸载原有的,只不过恰好卸载不掉其他方式挂载的而已 ...

smartmountfirmware好像做了处理的,原来有的没有卸载,原来没有的就卸载,恢复原状。哪怕是卸载不掉的巧合,也是很好的。

nttwqz 发表于 2021-1-13 14:24:59

liuzhaoyzz 发表于 2021-1-13 14:08
可能会有影响的。比如说这个引导盘符恰巧是当前系统的我的文档所转移到的盘符,强制卸载这个盘符之后,许 ...

我就是这么写的

liuzhaoyzz 发表于 2021-1-13 14:26:27

本帖最后由 liuzhaoyzz 于 2021-1-13 14:35 编辑

527104427 发表于 2021-1-13 14:21
有变通的方法:
ChkMbrPbr -ChkBootDrv-
先检测原先有没有盘符,如果没盘符,干完活再

set "ChkMbrPbr=%~sdp0ChkMbrPbr_x86.exe"
%ChkMbrPbr% -ChkBootDrv- 1>nul 2>nul || (
%ChkMbrPbr% -DelBootDrv
echo 已卸载启动分区%bootdisk2%:
)
哦,试了下,果然是可以!

CodeHz 发表于 2021-1-13 14:28:54

说到不小心卸载正在用的盘,我之前还遇到过,直接把d盘挂没了,还好mountvol还在,恢复回来了(
幸好没把c盘卸载了,那肯定就只能强制关机了

liuzhaoyzz 发表于 2021-1-13 14:32:07

CodeHz 发表于 2021-1-13 14:28
说到不小心卸载正在用的盘,我之前还遇到过,直接把d盘挂没了,还好mountvol还在,恢复回来了(
幸好没把c ...

不用mountvol也行啊,开始里面有磁盘管理,调出来给他分配个盘符即可。或者祭出bootice给他分配个盘符也行。我试了5大的程序没法卸载那种C盘的,就是引导文件和windows目录在一起的那种C盘,好像是卸载不掉的,这种卸载掉了,肯定会出岔子,这是对的。

liuzhaoyzz 发表于 2021-1-13 15:09:36

本帖最后由 liuzhaoyzz 于 2021-1-13 15:11 编辑

CodeHz 发表于 2021-1-13 14:28
说到不小心卸载正在用的盘,我之前还遇到过,直接把d盘挂没了,还好mountvol还在,恢复回来了(
幸好没把c ...
大神,你那边没有vc编译环境吗?你给的源代码能否用vc编译?我感觉vc编译的程序,360应该能过吧。大学时候学习谭浩强的《c语言程序设计》,早已还给老师了,我现在沦落到只能写“Hello world!”的程序了。

smartmountfirmware不完美的一点,就是不能过360杀软,虽然大家都知道这个没有病毒,但是向别人解释没有病毒要比写代码更让人心累。。。

liuzhaoyzz 发表于 2021-1-13 15:10:27

527104427 发表于 2021-1-13 14:54
你看下代码就知道了,卸载是排除了系统盘的。
为什么呢,因为我调试的时候就把系统盘干掉了,强制关机, ...

还好没把5大的硬盘搞坏,不然我的罪过就大了,你的硬盘里面一定有不少宝贝!记得多备份啊!云端,移动硬盘啥的多备份几份!

CodeHz 发表于 2021-1-13 15:19:05

liuzhaoyzz 发表于 2021-1-13 15:09
大神,你那边没有vc编译环境吗?你给的源代码能否用vc编译?我感觉vc编译的程序,360应该能过吧。大学时 ...

(vc当然有,但是版本都是2019的了,xp兼容模式早就没了(
这个改成vc兼容的倒也不难把那几个宏改成空的实现应该就好了(#include <tjs.h> 改成 #define scoped(x))后果就是泄露几个句柄,但是一次性运行的程序泄露没有关系(

nttwqz 发表于 2021-1-13 15:25:36

CodeHz 发表于 2021-1-13 14:28
说到不小心卸载正在用的盘,我之前还遇到过,直接把d盘挂没了,还好mountvol还在,恢复回来了(
幸好没把c ...

有一次我都吧C盘给卸载了,任务管理器cmd各种打不开只能重启了

liuzhaoyzz 发表于 2021-1-13 16:02:49

nttwqz 发表于 2021-1-13 15:25
有一次我都吧C盘给卸载了,任务管理器cmd各种打不开只能重启了

原来调试代码的时候,你也干过这样子的事情~~~

nttwqz 发表于 2021-1-13 17:34:35

本帖最后由 nttwqz 于 2021-1-13 17:37 编辑

liuzhaoyzz 发表于 2021-1-13 16:02
原来调试代码的时候,你也干过这样子的事情~~~

不是,很久之前突发奇想看能不能将C盘卸载了,一试果然能。
我干过更坑的事情,想当年一句命令错误导致把一个自己的硬盘执行了clean,更坑的是不能重建分区表示,只能数据恢复,哈哈哈哈。。。

liuzhaoyzz 发表于 2021-1-13 18:00:30

本帖最后由 liuzhaoyzz 于 2021-1-13 18:09 编辑

527104427 发表于 2021-1-13 12:08
麻烦最后测试一下,不行就彻底放弃了。
5大,好消息来了!
用这个版本的ChkMbrPbr测试结果都对了!bootmgr/bootmgfw.efi→PE.WIM结果也正确了!中文版、英文版操作系统都没问题。结果与CodeHz大神的smartmountfirmware有异曲同工之妙。ChkMbrPbr_x86.exe也是很容易被360咔嚓掉,是发给别人就被咔嚓掉了,不是运行过程中360提示放行这样子,这个有点郁闷。


奉上我写的与之搭配的拙劣的批处理:
@echo off
set "ChkMbrPbr=%~sdp0ChkMbrPbr_x86.exe"
for /f "tokens=1 delims=: " %%i in ('%ChkMbrPbr% -ChkBootDrv-') do set "bootdisk3=%%i"
for /f "tokens=1 delims=: " %%i in ('%ChkMbrPbr% -ChkBootDrv') do set "bootdisk2=%%i"
echo 启动分区=%bootdisk2%
if not defined bootdisk2 (
rem 如果ChkMbrPbr被360干掉
rem echo 从Z→C盘开始寻找BOOTMGR
for %%i in (Z Y X W V U T S R Q P O N M L K J I H G F E D C ) do (
dir /a %%i:\BOOTMGR 1>nul 2>nul && (
set bootdisk2=%%i
goto :next7
))
)
:next7
echo 启动分区=%bootdisk2%:
pause
if /i "%bootdisk3%"=="" (
%ChkMbrPbr% -DelBootDrv
echo 已卸载启动分区%bootdisk2%:
)
pause

感谢5大出手!


liuzhaoyzz 发表于 2021-1-13 19:50:12

527104427 发表于 2021-1-13 18:27
发现之前有几处输出弄错了,搞成错误输出了,导致批处理捕捉不到任何东西,再改一下吧:




感谢5大分享!

dos时代菜鸟 发表于 2021-1-13 20:59:17

本帖最后由 dos时代菜鸟 于 2021-1-13 23:40 编辑


这个 全 依赖 Diskpart+注册表 ,按理说 diskpart 的硬盘和分区序列应该 和 注册表中 记载的是一致的。
在 pe 下测试通过, win10 win7 下也通过。 等待测试中..............................

刚才有改进了一下,考虑 关键词 “卷”“volume” 在不同中英文环境下,可能会出问题,所以 同时比对之,如果有一个对应上,就算找到数据了,然后开展数据分析。


@echo off
setlocal ENABLEDELAYEDEXPANSION
rem 通过注册表获取 bcd 启动硬盘和分区,自动为其分配盘符,参数 /d 卸载盘符。

call:init
call:main script1
if errorlevel 1 (Echo Error!&&goto :end0)

if /i "%1"=="/d" (
    if not "!bcd_ltr!"=="" (
      set /p x=DisMount Volume , Press Enter to continue... X to Terminate...
      if /i "!x!"=="x" goto end0
      call:main script_down
    )
) else (
    if "!bcd_ltr!"=="" (
      set /p x=Mount Volume to !ltrs:~-1!:\ , Press Enter to continue... X to Terminate...
      if /i "!x!"=="x" goto end0
      call:main script_up
    )
)

pause
:end0
if exist %tempfile% del %tempfile%
goto :eof

rem --------------------------------------------------------------------------------------------------------
:init
for /f "tokens=2 delims=:" %%c in ('chcp') do (set page=%%c)
if !page! neq 936 (if !page! neq 437 (
      echo Page_code Error!
      goto :eof
))
set "ZH_str1=卷"
SET "EN_str1=Volume"

set "分割线=-------------------------------------------------------------------------------------------"
set tempfile="%temp%\%~n0.diskpart_script_temp"
set Used_LTRs=,
exit /b
:init_end
rem --------------------------------------------------------------------------------------------------------
:main
    for /f "tokens=3" %%c in ('reg query HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control /v FirmwareBootDevice') do (
      for /f "tokens=6,8 delims=()" %%h in ("%%c") do (
            if /i not "%%h"=="" (
                if /i not "%%j"=="" (
                  set "bcd_disk=%%h"
                  set "bcd_part=%%i"
                ) else (exit /b 1)) else (exlt /b 1)
      )
    )
    call:%1
    for /f "delims=" %%h in ('diskpart /s %tempfile%') do (
      set "l0=%%h"
      for /f "tokens=1,2 delims= " %%r in ("!l0:~1!") do (
            call:str_x str1 %%r
            if errorlevel 1 ( if /inot "%%s"=="###" (
                SET "ltr=!l0:~14,3!" && set "ltr=!ltr: =!"&& set Used_LTRs=!used_ltrs!,!ltr!
            ))
            if "!l0:~0,1!"=="*" (
                echo.
                echo !分割线!
                echo !l0!
                echo !分割线!
                set "bcd_ltr=!ltr!"
            )
      )
    )
    call:unltrs2
exit /b 0
:main_end
rem --------------------------------------------------------------------------------------------------------
:script0
    >%tempfile% echo sele disk !bcd_disk!
   >>%tempfile% echo sele part !bcd_part!
exit /b
:script0_end

:script1
    call:script0
    >>%tempfile% echo list vol
exit /b
:script1_end

:script_up
    call:script0
    >>%tempfile% echo assign letter=!ltrs:~-1!
    >>%tempfile% echo list vol
exit /b
:script_up_end

:script_down
    call:script0
    >>%tempfile% echo remove
    >>%tempfile% echo list vol
exit /b
:script_down_end
rem --------------------------------------------------------------------------------------------------------
:unltrs2
    set ltrs=
    set ltrs0=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    for %%c in (!used_ltrs!) do (set "ltrs0=!ltrs0:%%c=!")
    for %%c in (!ltrs0!) do (
      if not exist %%c:\ set "ltrs=!ltrs!%%c"
    )
exit /b
:unltrs2_end
rem --------------------------------------------------------------------------------------------------------
:str_x
rem 两个变量,%1= str1 str2 str3 等 存储关键字的变量名,%2=数值
rem 分别判断中文、英文 的关键字变量内容 与 数值是否一致,如果一致,返回1,否则返回0
    for %%x in (ZH EN) DO (    if /i "!%%x_%1!"=="%2" exit /b 1)
exit /b 0
:str_x_end




dos时代菜鸟 发表于 2021-1-13 21:41:28

本帖最后由 dos时代菜鸟 于 2021-1-13 23:39 编辑

发现 firmware64.exe 的问题:
当 pe 环境下 diskpart 把原本有盘符的 bcd 启动分区 更换了其他盘符,而 firmware64.exe 却还是判断成 原有盘符。
如图:


通常 win的各类 api 涉及分区卷挂载 都是先设置一个挂载点,然后再挂载,比如 wmi 中 win32_volume 中要先 addmountpoint 然后再 mount

这个 addmountpoint 的过程会记录到注册表中,我们也能通过其他手段获取这个 挂载点,
但是有的程序是 不设置挂载点而直接 挂载 盘符的,比如: diskpart .此时 要通过挂载点 判断 这个分区卷 是否被挂载了盘符,就 可能出现问题。

mountvol 卸载盘符,也是先删除这个挂载点 记录,再卸载盘符的,挂载点没有删除,mountvol 就还会体现出挂载点,造成貌似 盘符没有被卸载的假象。

个人理解:diskpart 更侧重于 对分区的 操作,而 api ,mountvol 等 则是侧重于卷 与系统 之间的通信联系。




CodeHz 发表于 2021-1-14 00:06:51

本帖最后由 CodeHz 于 2021-1-14 00:13 编辑

dos时代菜鸟 发表于 2021-1-13 21:41
发现 firmware64.exe 的问题:
当 pe 环境下 diskpart 把原本有盘符的 bcd 启动分区 更换了其他盘符,而 f ...
你是不是跑在不同的特权级别,看你标题一个管理员一个不是
这玩意挺复杂的,有全局的挂载,和会话的挂载两种方式,我firmware那个读挂载点是通过mountmgr读取的,这个读取到的是会话的挂载点信息。。。所以后面smartmount就干脆不用这个方法判断了,直接解析DosDevices,系统会帮我合并全局挂载点和会话挂载(或者符号链接)

你从我前面混乱的描述就能看出,这里起码有3种挂盘的方法。。。。(涉及3种不同的api,到内核层面都不同的那种)
subst的就是直接(会话级别的)符号链接,不会产生挂载点的(我smartmount就是利用subst相同原理,但是改了参数以支持挂载引导盘(选择这种是因为几乎没人用这个方法,不容易冲突)。。。(当然这种方法firmware读不到)

然后mountvol采用的方法是mountmgr系统服务(简单理解就是有uuid的,注册表看得到的,mountmgr负责维护uuid的对应关系)解析常规磁盘的挂载点,但是mountvol为引导分区做了特殊处理,你看显示的模式就和别的不一样,实际上是和uuid无关的(对应uuid的挂载点可以为空),所以有时候会出现mountvol读的到,而diskpart拿不到的情况(
wmi service也简单研究了一下,发现它同样也是利用mountmgr系统服务,所以它也可以拿不到已经挂载的引导分区的挂载情况

此外还有4种描述磁盘的方法,一种是直接\Device\HarddiskVolumeX(windows自己用的设备文件),一种是使用 \Device\HarddiskX\PartitionY(windows映射的符号链接,目标是前者),一种是用\ArcName\(引导时确定的,然后符号链接到前者)

还有就是用\Device里的uuid(mountmgr负责维护,也是符号链接到第一种),(然后这些路径还在\GLOBAL??里有映射,考虑有递归的情况,实际上可以有无数种路径描述同一个设备,这就是windows )

这也是我为啥放弃用mountmgr来读挂载点的原因,这玩意就坑爹,还是直接解析符号链接来的简单
页: 1 2 3 4 5 6 7 8 [9] 10 11 12 13 14
查看完整版本: 请问下有没有办法用批处理或者命令行小程序确定系统引导分区?