找回密码
 加入
搜索
查看: 797|回复: 12

[系统综合] UEFI启动电脑,PE卸载引导盘符(esp),不让显示电脑中

[复制链接]
发表于 2023-4-6 15:43:44 | 显示全部楼层 |阅读模式
本帖最后由 baosheng00 于 2023-4-6 15:48 编辑

论坛搜索没有查到没有可以卸载ESP分区的盘符,特来求助!F:盘就是要卸载的引导分区!获取bcd位置不够准确,有没有更好的方法?
      

1.获取bcd位置,判断盘符,无法卸载
$gudingpan = DriveGetDrive ("FIXED")
For $i = 1 To $gudingpan [0]
If FileExists($gudingpan [$i]&"\EFI\Microsoft\Boot\bcd") Then
$driveLetter=($gudingpan [$i])

EndIf
Next
$diskpartScript = "select volume " & $driveLetter & @CRLF & "remove letter=" & $driveLetter
; 运行diskpart命令
Run(@ComSpec & " /c echo " & $diskpartScript & " | diskpart")


2.mountvol.exe也无法删除盘符,其它盘可以正常删除
#include <Process.au3>
$gudingpan = DriveGetDrive ("FIXED")
For $i = 1 To $gudingpan [0]
     If FileExists($gudingpan [$i]&"\EFI\Microsoft\Boot\bcd") Then
       $driveLetter=($gudingpan [$i])
     EndIf
Next
_rundos("mountvol.exe " & $driveLetter & " /d")

3.使用批处理来删除,可以但是死板0分区,第一分区,如果不是无效
cmd /c "echo select disk 0 & echo select partition 1  & echo remove & echo exit"|diskpart.exe


所以请大家帮忙一下,用AU3编写,UEFI启动后,windwos卸载引导分区?(不要用DiskGenius之类手动删除,这个我会)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2023-4-6 19:00:17 来自手机 | 显示全部楼层
目的就是隐藏驱动器不是嘛,可以用注册表隐藏驱动。这样资源管理器里就不能查看到这个盘符了。
 楼主| 发表于 2023-4-6 19:30:47 | 显示全部楼层
gyp2000 发表于 2023-4-6 19:00
目的就是隐藏驱动器不是嘛,可以用注册表隐藏驱动。这样资源管理器里就不能查看到这个盘符了。

查过资料,是不是这两个位置,但都没有

保存了UEFI启动Windows系统时引导盘的盘符。在注册表路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment中,有一个名为SystemDrive的变量,它保存了系统盘的盘符。在UEFI启动时,这个变量会被设置为引导盘的盘符。

HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices键下的DosDevices中。其中,\Device\HarddiskVolume2表示引导盘的盘符



但都没有F盘的信息,应该F盘,进入PE桌面后加载的盘符,注册表不存在盘符

发表于 2023-4-7 00:05:56 | 显示全部楼层
baosheng00 发表于 2023-4-6 19:30
查过资料,是不是这两个位置,但都没有

保存了UEFI启动Windows系统时引导盘的盘符。在注册表路径HKEY_ ...

进入HKEY_CURRENT_USER\SoftWare\microsoft\Windows\CurrentVersion\Policies\Explorer分支中。
在右窗口中新建一个二进值的键值名为“NoDrives”,
   设定值为(十六进制),如下:
  不隐藏任何盘 0x00000000
  隐藏A盘 0x01000000
  隐藏B盘 0x02000000
  隐藏C盘 0x04000000
  隐藏D盘 0x08000000
  隐藏E盘 0x10000000
  隐藏F盘 0x20000000
  隐藏G盘 0x40000000
  隐藏H盘 0x80000000
发表于 2023-4-7 00:17:00 | 显示全部楼层
理论上用diskpart 也是可以隐藏esp,就是操作比较复杂。
需要先获取diskpart回显,然后分析回显数据找到需要操作的磁盘序号和分区序号,最后隐藏。
发表于 2023-4-7 08:21:41 | 显示全部楼层
能不能用命令:mountvol.exe  盘符 /d

 楼主| 发表于 2023-4-7 17:12:46 | 显示全部楼层
msold5 发表于 2023-4-7 08:21
能不能用命令:mountvol.exe  盘符 /d

帖子第二点

2.mountvol.exe也无法删除盘符,其它盘可以正常删除
发表于 2023-4-8 10:33:09 | 显示全部楼层
本帖最后由 gyp2000 于 2023-4-8 10:53 编辑
baosheng00 发表于 2023-4-7 17:12
帖子第二点

2.mountvol.exe也无法删除盘符,其它盘可以正常删除

DISKPART 删除盘符的例子:



#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
        Local $iPID, $aData, $PartList
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "LIST VOLUME" & @CRLF & "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        $PartList = StringRegExp($aData, "(?m)^.*?卷\h{5}(\d)\h{5}([A-Za-z])", 3)

        For $s = 0 To UBound($PartList) - 1 Step 2
                $aData = _WinAPI_GetDriveNumber($PartList[$s + 1] & ":")
                ConsoleWrite("驱动器:" & $PartList[$s + 1] & " 盘序号:" & $aData[1] & " 分区号:" & $aData[2] & @CRLF)
                If $PartList[$s + 1] = "E" Then DISKPART($aData[1], $aData[2])
                ;如果是驱动器E 则删除盘符
        Next
EndFunc   ;==>Example

Func DISKPART($DeviceNumber, $PartitionNumber)
        Local $iPID, $aData
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "SELECT DISK " & $DeviceNumber & @CRLF & _
                        "SELECT PARTITION " & $PartitionNumber & @CRLF & _
                        "REMOVE ALL NOERR" & @CRLF & _
                        "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        ConsoleWrite($aData)
EndFunc   ;==>DISKPART

发表于 2023-4-8 11:13:24 | 显示全部楼层
本帖最后由 gyp2000 于 2023-4-8 11:31 编辑

也可以正则直接提取磁盘容量,然后根据容量大小删除盘符。


不过win7 win8.1 win10 下的 DISKPART.EXE 返回信息可能不完全一样,一个正则无法适配所有系统。
如果用其他办法判断分区是否需要隐藏,那么只需要用 _WinAPI_GetDriveNumber 获取盘序号和分区号,
就可以调用 DISKPART.EXE 删除盘符了。




#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>

Example()

Func Example()
        Local $iPID, $aData, $PartList
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "LIST VOLUME" & @CRLF & "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        ConsoleWrite($aData)
        $PartList = StringRegExp($aData, "(?m)^.*?卷\h{5}\d\h{5}([A-Za-z]).*?磁盘分区\h*?(\d+)*\h*?MB", 3)
        If @error Then Return
        For $s = 0 To UBound($PartList) - 1 Step 2
                If int($PartList[$s + 1]) > 100 Then ;如果分区容量大于 100MB 并且有盘符,则删除盘符
                $aData = _WinAPI_GetDriveNumber($PartList[$s] & ":")
                DISKPART($aData[1], $aData[2])
                ConsoleWrite("驱动器:" & $PartList[$s] & " 盘序号:" & $aData[1] & " 分区号:" & $aData[2] & @CRLF)
                EndIf
        Next
EndFunc   ;==>Example

Func DISKPART($DeviceNumber, $PartitionNumber)
        Local $iPID
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "SELECT DISK " & $DeviceNumber & @CRLF & _
                        "SELECT PARTITION " & $PartitionNumber & @CRLF & _
                        "REMOVE ALL NOERR" & @CRLF & _
                        "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        ConsoleWrite($aData)
EndFunc   ;==>DISKPART




点评

谢谢,根据容量,一些大于1G的,会误导不准确  发表于 2023-4-8 13:20
 楼主| 发表于 2023-4-8 12:52:37 | 显示全部楼层
gyp2000 发表于 2023-4-8 10:33
DISKPART 删除盘符的例子:

谢谢,测试还是不行。
#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>

#include <File.au3>
$drives = DriveGetDrive("FIXED")
$esp_drive = ""
For $i = 1 To $drives[0]
    $drive_fs = DriveGetFileSystem($drives[$i])
    If $drive_fs = "FAT32" Or $drive_fs = "FAT16" Or $drive_fs = "FAT" Then
        $bcd_file = $drives[$i] & "\EFI\Microsoft\Boot\BCD"
        If FileExists($bcd_file) Then
            $esp_drive = $drives[$i]
            ExitLoop
        EndIf
    EndIf
Next



;MsgBox(16+0, "错误", $esp_drive,8)

Example()

Func Example()
        Local $iPID, $aData, $PartList
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "LIST VOLUME" & @CRLF & "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        $PartList = StringRegExp($aData, "(?m)^.*?卷\h{5}(\d)\h{5}([A-Za-z])", 3)

        For $s = 0 To UBound($PartList) - 1 Step 2
                $aData = _WinAPI_GetDriveNumber($PartList[$s + 1] & ":")
                ConsoleWrite("驱动器:" & $PartList[$s + 1] & " 盘序号:" & $aData[1] & " 分区号:" & $aData[2] & @CRLF)
                If $PartList[$s + 1] = $esp_drive Then DISKPART($aData[1], $aData[2])
                ;如果是驱动器E 则删除盘符
        Next
EndFunc   ;==>Example

Func DISKPART($DeviceNumber, $PartitionNumber)
        Local $iPID, $aData
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "SELECT DISK " & $DeviceNumber & @CRLF & _
                        "SELECT PARTITION " & $PartitionNumber & @CRLF & _
                        "REMOVE ALL NOERR" & @CRLF & _
                        "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        ConsoleWrite($aData)
EndFunc   ;==>DISKPART

Exit

$esp_drive,可以获取到,盘符,但函数 DISKPART()未执行

发表于 2023-4-8 18:19:34 来自手机 | 显示全部楼层
本帖最后由 gyp2000 于 2023-4-8 19:11 编辑

上边写的只是例子。如果打算直接调用还需要改一下。
#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>
#include <File.au3>
$drives = DriveGetDrive("FIXED")
$esp_drive = ""
For $i = 1 To $drives[0]
    $drive_fs = DriveGetFileSystem($drives[$i])
    If $drive_fs = "FAT32" Or $drive_fs = "FAT16" Or $drive_fs = "FAT" Then
        $bcd_file = $drives[$i] & "\EFI\Microsoft\Boot\BCD"
        If FileExists($bcd_file) Then
            $esp_drive = $drives[$i]
            ExitLoop
        EndIf
    EndIf
Next
DISKPART($esp_drive)

Func DISKPART($DriveNumber)
        Local $iPID, $aData
        $aData = _WinAPI_GetDriveNumber($DriveNumber)
        If @error Then Return
        $iPID = Run(@SystemDir & "\DISKPART.EXE", @SystemDir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($iPID, "SELECT DISK " & $aData[1] & @CRLF & _
                        "SELECT PARTITION " & $aData[2] & @CRLF & _
                        "REMOVE ALL NOERR" & @CRLF & _
                        "Exit" & @CRLF)
        While ProcessExists($iPID)
                Sleep(10)
        WEnd
        $aData = BinaryToString(StdoutRead($iPID, False, True))
        ConsoleWrite($aData)
EndFunc   ;==>DISKPART

 楼主| 发表于 2023-4-9 07:30:22 | 显示全部楼层
gyp2000 发表于 2023-4-8 18:19
上边写的只是例子。如果打算直接调用还需要改一下。

谢谢,试了还是不能卸载。叫ai写一个
; 生成 unmount_boot_drive.txt 文件
Func GenerateUnmountScript($sDriveLetter)
    Local $sScriptPath = @TempDir & "\unmount_boot_drive.txt"
    Local $sScriptContent = "select volume " & $sDriveLetter & @CRLF & "remove letter " & $sDriveLetter & @CRLF & "exit"
    Local $hFile = FileOpen($sScriptPath, 2)
    If $hFile = -1 Then Return False
    FileWriteLine($hFile, $sScriptContent)
    FileClose($hFile)
    Return $sScriptPath
EndFunc

; 查找电脑引导盘符
Func FindBootDrive()
    Local $sDriveLetter = ""
    Local $aDrives = DriveGetDrive("ALL")
    For $i = 1 To $aDrives[0]
        If DriveGetType($aDrives[$i]) = "Fixed" And StringInStr(FileGetAttrib($aDrives[$i]), "F") And FileExists($aDrives[$i] & "\EFI\Microsoft\Boot\BCD") Then
            $sDriveLetter = StringUpper(StringLeft($aDrives[$i], 1))
            ExitLoop
        EndIf
    Next
    If $sDriveLetter <> "" Then Return GenerateUnmountScript($sDriveLetter)
    Return False
EndFunc

; 卸载引导盘符
Func UnmountBootDrive()
    Local $sScriptPath = FindBootDrive()
    If $sScriptPath <> False Then
        RunWait(@ComSpec & " /c diskpart /s " & $sScriptPath, @SystemDir, @SW_HIDE)
        FileDelete($sScriptPath)
        Return True
    EndIf
    Return False
EndFunc

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-22 11:02 , Processed in 0.089044 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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