Jump to content
graves

Trouble with diskpart.exe script

Recommended Posts

graves

Greetings. I'm running in to a problem with my second AutoIt script and can't seem to figure it out. The script is supposed to loop through every disk listed and capture the disk detail to a text file named with disk id (disk 0.txt, disk 1.txt, etc). Then it searches each text file for the string "Type   : USB" and if found, deletes that file leaving only text files relating to fixed disks. Finally it uses the remaining file names as without the .txt extension for the "select disk" command before performing the rest of the commands in diskpart to repartition and format the drives.

Each function performs as expected but when I run the script, the function FormatFixedDisks() seems to execute before the text files containing the "USB" string get deleted so it ends up formatting all disks connected to the system. In the code below I've commented out the diskpart formatting commands and leaving only "select disk" output to a message box to test. I've tried messing around with sleep functions to no avail and besides, i don't think thats the root cause here.

Reason I want to avoid USB disk types is because I'm running a disk wipe tool bundled with MS Diagnostics and Recovery Toolset in WinPE on servers via USB stick and don't want to wipe the stick obviously. After blowing out the RAID config I was having to manually reformat each disk in diskpart before executing the wipe process.

What am I missing?

Thanks!

#include <Constants.au3>
#include <File.au3>
#include <Array.au3>

DirCreate("Disks")
$diskIDs = GetDiskListings()
GetDiskDetails($diskIDs)
DeleteDiskTypeUSBFiles()
FormatFixedDisks()

Func GetDiskListings()
    Local $diskPart = ""
    Local $listDisk = ""
    Local $listOfDisks = ""

    Local $diskPart = Run("diskpart.exe", "C:\Windows\System32\", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
    StdinWrite($diskPart, "list disk")
    StdinWrite($diskPart)

    ;Read from child's STDOUT and show
    Local $listDisk
    While True
      $listDisk &= StdoutRead($diskPart)
      If @error Then ExitLoop
      Sleep(25)
    WEnd

    $listOfDisks = StringRegExp($listDisk, '(Disk\s\d)', 3) ;Returns array of all disks from list disk output.
    Return $listOfDisks
EndFunc

Func GetDiskDetails($listOfDisks)
    Local $disks = ""
    Local $diskPart = ""
    Local $diskDetails = ""

    $disks = $listOfDisks

    For $disk In $disks
        $diskPart = Run("diskpart.exe", "C:\Windows\System32\", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
        StdinWrite($diskPart, "select " & $disk & @CRLF & "detail disk")
        StdinWrite($diskPart)

        While True
            $diskDetails &= StdoutRead($diskPart)
            If @error Then ExitLoop
                Sleep(25)
        WEnd

        ;Create new file using $disk as filename and write diskpart output to file. 
        FileOpen("Disks\" & $disk & ".txt", 1)
        FileWrite("Disks\" & $disk & ".txt", $diskDetails)
        FileClose("Disks\" & $disk & ".txt")

        $diskDetails = ""
    Next
EndFunc

Func DeleteDiskTypeUSBFiles()
    Local $error = False
    Local $files = ""

    If FileExists(".\Disks") Then
        $files = _FileListToArray("Disks", "*")
        _ArrayDelete($files, 0) ;Delete first element because it's only number of rows.
        For $file In $files
            ;Read all lines in $diskFile and search for string "USB".
            Local $arrDiskContents
            _FileReadToArray("Disks\" & $file, $arrDiskContents)

            ;Write each line in array to new string variable because _ArraySearch for
            ;string would not work. 
            Local $strDiskContents
            For $line In $arrDiskContents
                $strDiskContents &= $line & @CRLF
            Next
            If StringInStr($strDiskContents, "Type   : USB") Then
                FileDelete("Disks\" & $file)
            EndIf
            $strDiskContents = ""
        Next
    Else
        MsgBox(0, "Error", "The Disks directory could not be found." & @LF & _ 
        "The script cannot continue.")
        $error = True
        Exit
    EndIf
    Return $error
EndFunc

Func FormatFixedDisks()
    Local $error = False
    Local $files = ""
    Local $diskPart = ""
    Local $diskDetails = ""

    If FileExists(".\Disks") Then
        $files = _FileListToArray("Disks", "*")
        _ArrayDelete($files, 0) ;Delete first element because it's only number of rows.
        _ArrayTrim($files, 4, 1) ;Trim file extension for select disk input.

        For $file In $files
            $diskPart = Run("diskpart.exe", "C:\Windows\System32\", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
            StdinWrite($diskPart, "select " & $file); & @CRLF & "clean" & @CRLF & "create partition primary" & @CRLF & "format fs=ntfs quick" & @CRLF & "assign")
            StdinWrite($diskPart)
            While True
                $diskDetails &= StdoutRead($diskPart)
                If @error Then ExitLoop
                    Sleep(25)
            WEnd
        
            MsgBox(0, "DiskPart Results", $diskDetails, .500)
            $diskDetails = ""
        Next
    EndIf
EndFunc
  • Like 1

Share this post


Link to post
Share on other sites
graves

Well...got it working by appending a different extension to the file containing the string "Type   : USB" and filtering on only .txt files in the FormatFixedDisks() function thereby only partitioning the fixed disks. I did observe that FileDelete() would return True before the files were actually deleted. FileRecycle() seemed to work when testing on my machine but didn't work in WinPE because there is no recycle bin. Whole project feels like a hack but it gets the job done.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×