baosheng00 发表于 2023-4-6 15:43:44

UEFI启动电脑,PE卸载引导盘符(esp),不让显示电脑中

本帖最后由 baosheng00 于 2023-4-6 15:48 编辑

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

1.获取bcd位置,判断盘符,无法卸载
$gudingpan = DriveGetDrive ("FIXED")
For $i = 1 To $gudingpan
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
   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之类手动删除,这个我会)

gyp2000 发表于 2023-4-6 19:00:17

目的就是隐藏驱动器不是嘛,可以用注册表隐藏驱动。这样资源管理器里就不能查看到这个盘符了。

baosheng00 发表于 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桌面后加载的盘符,注册表不存在盘符

gyp2000 发表于 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

gyp2000 发表于 2023-4-7 00:17:00

理论上用diskpart 也是可以隐藏esp,就是操作比较复杂。
需要先获取diskpart回显,然后分析回显数据找到需要操作的磁盘序号和分区序号,最后隐藏。

msold5 发表于 2023-4-7 08:21:41

能不能用命令:mountvol.exe盘符 /d

baosheng00 发表于 2023-4-7 17:12:46

msold5 发表于 2023-4-7 08:21
能不能用命令:mountvol.exe盘符 /d

帖子第二点

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

gyp2000 发表于 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}()", 3)

      For $s = 0 To UBound($PartList) - 1 Step 2
                $aData = _WinAPI_GetDriveNumber($PartList[$s + 1] & ":")
                ConsoleWrite("驱动器:" & $PartList[$s + 1] & " 盘序号:" & $aData & " 分区号:" & $aData & @CRLF)
                If $PartList[$s + 1] = "E" Then DISKPART($aData, $aData)
                ;如果是驱动器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

gyp2000 发表于 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}().*?磁盘分区\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, $aData)
                ConsoleWrite("驱动器:" & $PartList[$s] & " 盘序号:" & $aData & " 分区号:" & $aData & @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




baosheng00 发表于 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
    $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}()", 3)

      For $s = 0 To UBound($PartList) - 1 Step 2
                $aData = _WinAPI_GetDriveNumber($PartList[$s + 1] & ":")
                ConsoleWrite("驱动器:" & $PartList[$s + 1] & " 盘序号:" & $aData & " 分区号:" & $aData & @CRLF)
                If $PartList[$s + 1] = $esp_drive Then DISKPART($aData, $aData)
                ;如果是驱动器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()未执行

gyp2000 发表于 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
    $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 & @CRLF & _
                        "SELECT PARTITION " & $aData & @CRLF & _
                        "REMOVE ALL NOERR" & @CRLF & _
                        "Exit" & @CRLF)
      While ProcessExists($iPID)
                Sleep(10)
      WEnd
      $aData = BinaryToString(StdoutRead($iPID, False, True))
      ConsoleWrite($aData)
EndFunc   ;==>DISKPART


baosheng00 发表于 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
      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

页: [1]
查看完整版本: UEFI启动电脑,PE卸载引导盘符(esp),不让显示电脑中