bfgxp 发表于 2016-12-2 09:19:54

利用snapshot --show参数提取磁盘及分区信息!

本帖最后由 bfgxp 于 2016-12-2 11:47 编辑



snapshot.exe下载
#include <Array.au3>
#include <WinAPIFiles.au3>
_Part_info()
Func _Part_info()
      $foo = Run("snapshot.exe --show", "", @SW_HIDE, $STDOUT_CHILD)
      ProcessWaitClose($foo)
      $text = StdoutRead($foo) & @CRLF & @CRLF & "ABC:)"
      ;$Disks = StringRegExp($text, "\b.+Vendor.+", 3)
      $DisksAndParts = StringRegExp($text, "(?s)HD\d+\h+\(FIXED.+?\n\r", 3)
      For $i = 0 To UBound($DisksAndParts) - 1
                $Disk = StringRegExp($DisksAndParts[$i], "\b.+Vendor.+", 3)
                $parts = StringRegExp($DisksAndParts[$i], "\b.+\(S=.+", 3)
                Dim $PartINfoS
                For $j = 0 To UBound($parts) - 1
                        $PartInfo = StringSplit(StringStripWS($parts[$j], 4), " ")
                        $PartINfoS[$j] = _DriveNum($PartInfo)
                        If Not StringRegExp($PartInfo, "\:\d") Then $PartINfoS[$j] = $PartInfo
                        $PartINfoS[$j] = $PartInfo
                        $PartINfoS[$j] = StringReplace($PartInfo, "(S=", "")
                        $PartINfoS[$j] = _PartSize($PartInfo)
                        $PartINfoS[$j] = Int(DriveSpaceFree($PartInfo & "\") / 1024) & " GB"
                        If $PartInfo = 7 Then $PartINfoS[$j] = $PartInfo
                Next
                _ArraySort($PartINfoS)
                _ArrayDisplay($PartINfoS, StringStripWS($Disk, 4))
      Next
EndFunc   ;==>_Part_info
Func _PartSize($PartInfo4)
      $PartSize = Int(StringRegExpReplace($PartInfo4, "\D", "") / 1024)
      If StringRegExp($PartInfo4, "\dB") Then $PartSize = $PartSize & " KB"
      If StringRegExp($PartInfo4, "\dKB") Then $PartSize = $PartSize & " MB"
      If StringRegExp($PartInfo4, "\dMB") Then $PartSize = $PartSize & " GB"
      Return $PartSize
EndFunc   ;==>_PartSize
Func _DriveNum($PartInfo1)
      If StringRegExp($PartInfo1, "\:\d") Then
                $DriveNum = StringReplace($PartInfo1, "HD", "")
      Else
                $aData = _WinAPI_GetDriveNumber($PartInfo1)
                $DriveNum = Ceiling($aData + 1) & ":" & $aData
      EndIf
      Return $DriveNum
EndFunc   ;==>_DriveNum

chzj589 发表于 2016-12-2 10:09:31

回复 1# bfgxp
运行后没显示???

chzj589 发表于 2016-12-2 10:15:13

回复 2# chzj589

"F:\论坛案例\路由器自动导入配置文件\提取磁盘及分区信息.au3"(6,70) : error: $STDOUT_CHILD: undeclared global variable.
      $foo = Run("snapshot.exe --show", "", @SW_HIDE, $STDOUT_CHILD)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

bfgxp 发表于 2016-12-2 11:45:05

你得自己下载snapshot.exe
http://www.drivesnapshot.de/download/snapshot.exe

chzj589 发表于 2016-12-2 16:53:56

回复 4# bfgxp
谢谢分享!

bfgxp 发表于 2016-12-3 13:48:13

回复 5# chzj589
不谢,你是怎么判断分区中安装的系统的?

chzj589 发表于 2016-12-3 16:26:46

回复chzj589
不谢,你是怎么判断分区中安装的系统的?
bfgxp 发表于 2016-12-3 13:48 http://www.autoitx.com/images/common/back.gif

自己就显示啊

chishingchan 发表于 2016-12-4 13:55:26

我也收藏了一份这样功能的脚本,希望对你有帮助!#include <include\SetupAPI.au3>
#include <array.au3>

For $number = 0 To RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum","count")-1
        Global $Device_0 = "\\.\PhysicalDrive" & $number
        Global $Log_Partition_Array
        Global $Master_Partition_Table
        Global $output
        _Get_Partition()
Next

Func _Get_Partition()
        $y = StringRight($Device_0, 1)
        $san = _Device_Read($Device_0, 0, 1)
        $Master_Partition_Table = _GetPartitionTable($san)
        $Partition_Array = Get_Ext_Patition()
        $z = 1
        ReDim $Partition_Array
        For $r = 0 To UBound($Partition_Array) - 1
                If StringInStr($Partition_Array[$r],"Pri") Then
                        $Partition_Array[$r] = $y + 1 & ":" & $z
                        $z += 1
                EndIf
        Next
        For $i = 0 To UBound($Partition_Array) - 1
                If $Partition_Array[$i] = "Ext" Then
                        _Get_Log_partition('0x' & $Partition_Array[$i])
                EndIf
        Next

        For $k = 0 To UBound($Partition_Array) - 1
                $Partition_Array[$k] = Execute("0x" & $Partition_Array[$k])
        Next
        _ArrayDelete($Log_Partition_Array, UBound($Log_Partition_Array) - 1)
        Dim $Number_A = UBound($Partition_Array), $Number_B = UBound($Log_Partition_Array)
        ReDim $Partition_Array[$Number_A + $Number_B]
        $k = 0
        For $i = $Number_A To $Number_A + $Number_B - 1
                For $n = 0 To 4
                        $Partition_Array[$i][$n] = $Log_Partition_Array[$k][$n]
                Next
                $k += 1
                $Partition_Array[$i] = $y + 1 & ":" & $k + 1 + ($r - 2)
        Next
        _ArrayDisplay($Partition_Array,$Device_0)
EndFunc

Func Get_Ext_Patition()
        Local $Partition
        For $i = 0 To 15 Step 4
                $n = UBound($Partition)
                Dim $str = ''
                For $k = $i To $i + 3
                        $str &= $Master_Partition_Table[$k]
                Next
                If $str == '00000000000000000000' Then
                        ExitLoop
                Else
                        ReDim $Partition[$n + 1]
                        $Partition[$n - 1] = $Master_Partition_Table[$i]
                        $Partition[$n - 1] = $Master_Partition_Table[$i + 1]
                        $Partition[$n - 1] = $Master_Partition_Table[$i + 2]
                        $Partition[$n - 1] = $Master_Partition_Table[$i + 3]
                EndIf
        Next
        For $a = 0 To UBound($Partition) - 2
                $Size = Round(("0x" & $Partition[$a])*512/1024/1024,2)
                If $Partition[$a] = "80" Then
                        $Partition[$a] = "Pri"
                        $Partition[$a] = "A"
                        If StringLeft($Partition[$a],1) = 1 Then $Partition[$a] = "AH"
                        $Partition[$a] = $Size
                ElseIf $Partition[$a] == '0F' Then
                        $Partition[$a] = "Ext"
                        $Partition[$a] = ""
                        If StringLeft($Partition[$a],1) = 1 Then $Partition[$a] = "H"
                        $Partition[$a] = $Size
                Else
                        If $Partition[$a] = "80" Then
                                $var = "A"
                                If StringLeft($Partition[$a],1) = 1 Then $var="AH"
                        Else
                                $var = ""
                                If StringLeft($Partition[$a],1) = 1 Then $var="H"
                        EndIf
                        $Partition[$a] = "Pri"
                        $Partition[$a] = $var
                        $Partition[$a] = $Size
                EndIf
        Next
        ReDim $Partition
        Return $Partition
EndFunc   ;==>Get_Ext_Patition


Func _Get_Log_partition($Sector)
        $Log = _Device_Read($Device_0, $Sector, 1)
        $Master_Partition_Table = _GetPartitionTable($Log)

        Local $Log_Partition
        For $i = 0 To 15 Step 4
                $n = UBound($Log_Partition)
                Dim $str = ''
                For $k = $i To $i + 3
                        $str &= $Master_Partition_Table[$k]
                Next
                If $str == '00000000000000000000' Then
                        ExitLoop
                Else
                        ReDim $Log_Partition[$n + 1]
                        $Log_Partition[$n - 1] = "Log"
                        $Log_Partition[$n - 1] = $Master_Partition_Table[$i]
                        $Log_Partition[$n - 1] = $Master_Partition_Table[$i + 1]
                        $Log_Partition[$n - 1] = $Master_Partition_Table[$i + 2]
                        $Log_Partition[$n - 1] = $Master_Partition_Table[$i + 3]
                EndIf
        Next

        $Sector_Start = $Sector + Execute('0x' & $Log_Partition)
        If $Log_Partition = '00' Then $Log_Partition = ' '
        If StringLeft($Log_Partition,1) = 1 Then $Log_Partition='H'
        $Size = Round(("0x" & $Log_Partition)*512/1024/1024,2)
        $A_number = UBound($Log_Partition_Array)
        ReDim $Log_Partition_Array[$A_number + 1]
        $Log_Partition_Array[$A_number - 1] = $Log_Partition
        $Log_Partition_Array[$A_number - 1] = $Log_Partition
        $Log_Partition_Array[$A_number - 1] = $Log_Partition
        $Log_Partition_Array[$A_number - 1] = $Sector_Start
        $Log_Partition_Array[$A_number - 1] = $Size

        $Sector1 = Execute('0x' & $Log_Partition) + $Sector + Execute('0x' & $Log_Partition)
        If UBound($Log_Partition) > 2 Then
                _Get_Log_partition($Sector1)
        Else
                Return $Log_Partition_Array
        EndIf
EndFunc   ;==>_Get_Log_partition

Func _Device_Read($DeviceID, $Offset, $Length = 1)
        Local $Pos, $Size, $Result
        If StringInStr($Offset, "0x") Then
                If Not IsBinary($Offset) Then $Pos = Execute(Binary($Offset)) * 512
        Else
                $Pos = $Offset * 512
        EndIf
;MsgBox("","$Pos",$Pos)
        $Size = $Length * 512
;MsgBox("","$Size",$Size)
        $hFile = _CM_Create_File($DeviceID, 0xC0000000, 3, 0, 3, 0)
;MsgBox("","$hFile",$hFile)
        _NtSetInformationFile($hFile, 14, $Pos, 8, "int64*")
        $pBuffer = _CM_Heap_Alloc($Size)
        _CM_Read_Device($hFile, $pBuffer, $Size)
        _CM_Close_Handle($hFile)
        $tBuffer = DllStructCreate("byte Binary[" & $Size & "]", $pBuffer)
        $Result = DllStructGetData($tBuffer, "Binary")
        Return $Result
EndFunc   ;==>_Device_Read

Func _NtSetInformationFile($hFile, $iInfoClass, $vBuffer, $iBuffer, $sBufferType = "ptr")
        Local $iResult, $tStatus, $pStatus
        $tStatus = DllStructCreate("ubyte Status")
        $pStatus = DllStructGetPtr($tStatus)
        $iResult = DllCall("Ntdll.dll", "dword", "NtSetInformationFile", "handle", $hFile, "ptr", $pStatus, $sBufferType, $vBuffer, "ulong", $iBuffer, "dword", $iInfoClass)
        Return SetError($iResult, 0, $iResult = 0)
EndFunc   ;==>_NtSetInformationFile

Func _GetPartitionTable($SectorData)
        Const $PriPT_FirstAction = 0x01BE + 1; 1 Byte
        Local $aPartTable
        $PriPT_data = BinaryMid($SectorData, $PriPT_FirstAction, 0x40)
        $aPartTable = StringRegExp(StringTrimLeft($PriPT_data, 2), '(\S{2})\S{6}(\S{2})\S{6}(\S{8})(\S{8})', 3)
        $arraynum = UBound($aPartTable) - 1
        For $i = 0 To $arraynum
                $aPartTable[$i] = _SwapHexData($aPartTable[$i])
        Next
        Return $aPartTable
EndFunc   ;==>_GetPartitionTable

Func _SwapHexData($data)
        Local $Result
        $sLen = StringLen($data)
        For $i = 1 To $sLen Step 2
                $Result = StringMid($data, $i, 2) & $Result
        Next
        Return $Result
EndFunc   ;==>_SwapHexData

chzj589 发表于 2016-12-4 16:10:45

回复 8# chishingchan

#include <include\SetupAPI.au3>???

chishingchan 发表于 2016-12-4 16:17:03

回复 9# chzj589

chzj589 发表于 2016-12-4 16:32:09

回复 10# chishingchan
下载了,SetupAPI.au3里缺
LocalSecurityAuthority.au3 ???

chzj589 发表于 2016-12-4 16:46:17

我也收藏了一份这样功能的脚本,希望对你有帮助!
chishingchan 发表于 2016-12-4 13:55 http://www.autoitx.com/images/common/back.gif



没盘符??

coolijoanne 发表于 2016-12-6 08:17:28

學習了!!這是個ˇ不錯的方式!!

bfgxp 发表于 2016-12-6 19:28:37

回复 7# chzj589


    这个显示的是卷标,可不是安装的系统。

bfgxp 发表于 2016-12-6 19:31:30

回复 8# chishingchan


    曾经尝试使用这段代码的,纯au3实现,只是SetupAPI.au3有多个版本吧,LocalSecurityAuthority.au3似乎还改过名,忘记了。
所以干脆用第三方程序,snapshot小巧实用,用正则提取,代码也要简单得多。
页: [1] 2
查看完整版本: 利用snapshot --show参数提取磁盘及分区信息!