Automating DiskPart with Windows PowerShell: Part 4

Automating DiskPart with Windows PowerShell: Part 4

  • Comments 7
  • Likes

Summary: Use Windows PowerShell to build scripts to automate DiskPart.

Hey, Scripting Guy! Question Hey, Scripting Guy! Can we use Windows PowerShell to return information from DiskPart as an object?

—SH

Hey, Scripting Guy! Answer Hello SH,

Honorary Scripting Guy, Sean Kearney, here. I’m filling in for our good friend, Ed Wilson. He’s got tie’s everywhere! Ties all over his property! The problem is they’re running amok! You see, he’s turned into a “tie” fighter (and may the farce be with you).

Today we’re going to pull all of this together into a function that we’re going to call Get-DiskPartInfo. We will pull all of these scripts together to automatically parse through the disks in DiskPart, pull their data, and return it as a [pscustomobject].

Note   This is Part 4 in a series. If you are behind, please read:

So shall we get started? First we define our function, but we’ll attach the appropriate parameters and make this a true advanced function:

Function GET-DISKPARTINFO() {

[cmdletbinding()]

Param()

Now let’s add our first DiskPart script to get the number of drives:

NEW-ITEM –name listdisk.txt –itemtype file –force | OUT-NULL
ADD-CONTENT –path listdisk.txt “LIST DISK”
$LISTDISK=(DISKPART /S LISTTDISK.TXT)
$TOTALDISK=($LISTDISK.Count)-9          

Then we can loop through each disk, grabbing the DiskID and its physical size:

for ($d=0;$d -le $TOTALDISK;$d++)

{

$SIZE=$LISTDISK[-1-$d].substring(25,9).replace(" ","")
$DISKID=$LISTDISK[-1-$d].substring(7,5).trim()

Now that we have the DiskID, we can write a simple script for DiskPart to call up that disk and grab it’s Detail:

NEW-ITEM -Name detail.txt -ItemType file -force | OUT-NULL
ADD-CONTENT -Path detail.txt "SELECT DISK $DISKID"
ADD-CONTENT -Path detail.txt "DETAIL DISK"
$DETAIL=(DISKPART /S DETAIL.TXT)

And now with the Detail for that disk in hand, we run through our Detail parsing to pull the information we need from there:

$MODEL=$DETAIL[8]
$TYPE=$DETAIL[10].substring(9)
$DRIVELETTER=$DETAIL[-1].substring(15,1)

Now we take a few minutes to convert that drive size to a real integer that we can use to compare the size of the removable disk:

$LENGTH=$SIZE.length
$MULTIPLIER=$SIZE.substring($length-2,2)
$INTSIZE=$SIZE.substring(0,$length-2)

SWITCH($MULTIPLIER)
 {
  KB { $MULT = 1KB }
  MB { $MULT = 1MB }
  GB { $MULT = 1GB }
 }

$DISKTOTAL=([convert]::ToInt16($INTSIZE,10))*$MULT

Then all we need do now is wrap it up neatly as a custom object in Windows PowerShell:

[pscustomobject]@{DiskNum=$DISKID;Model=$MODEL;Type=$TYPE;DiskSize=$DISKTOTAL;DriveLetter=$DRIVELETTER}
}
}

Pull this advanced function together and you can turn the following information…

Image of command output

…into useful output like the following in Windows PowerShell:

Image of command output

Now we can even do something like this:

GET-DISKPARTINFO | WHERE { $_.Type –eq ‘USB’ –and $_.DiskSize -lt16GB }

Here’s where things are going to be interesting tomorrow. With all this information as an object, I’ll bet you’re wondering if I can go the next level, and automatically format those USB keys. Check in tomorrow for our final segment where we’ll tie all of this into that and automatically build a key from Microsoft Deployment Tootkit (MDT) 2012!

I invite you to follow us on Twitter and Facebook. If you have any questions, send email to Ed at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Sean Kearney (filling in for our good friend Ed Wilson),
      Honorary Scripting Guy, Windows PowerShell MVP
           …and good personal friend of the BATCHman

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • To keep the WMI alternative going, here's a way to get the same information.  Most of these fields are already in the Win32_DiskDrive class (with alternate names); the exception is Drive Letters.  For that, you have to walk through some associated objects (the closest one being Win32_LogicalDisk).  Here's an example of this (the one difference being that the "DriveLetter" scalar property has been changed to a "DriveLetters" array, since physical drives can have more than one partition or volume).

    ##########################################

    function Get-DiskInfo

    {

       [CmdletBinding()]

       param ( )

       $diskDrives = Get-WmiObject -Class Win32_DiskDrive

       foreach ($diskDrive in $diskDrives)

       {

           $driveLetters = @()

           $partitions = Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='$($diskDrive.DeviceID)'} WHERE ResultClass = Win32_DiskPartition"

           foreach ($partition in $partitions)

           {

               $logicalDisks = Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} WHERE ResultClass = Win32_LogicalDisk"

               foreach ($logicalDisk in $logicalDisks)

               {

                   $driveLetters += $logicalDisk.Name -replace ':$'

               }

           }

           New-Object PSObject -Property @{

               DiskNum = $diskDrive.Index

               Model = $diskDrive.Model

               Type = $diskDrive.InterfaceType

               DiskSize = $diskDrive.Size

               DriveLetters = $driveLetters

           }

       }

    }

    Get-DiskInfo | Format-Table

  • That code didn't format particularly well in a blog comment, but it does run if you copy and paste it into the ISE; I checked.  You'll have to delete all the extra blank lines yourself, if they bother you.

  • @David - once again you are taking all of the fun out of this exercise.  We know most things can be gotten from WMI however, there is some partition info that is not available on all systems through WMI.  Knowing how to parse a very complex text sequence is useful.

    Maybe this weekend I will take a stab at doing some with RegEx.  Sean seems to have completely covered how to do it with string primitives.

    Parsing text can be fun.

  • As I mentioned in the comments for Part 1 of this series, trying to parse text output from a command-line utility can be unreliable.  These tools sometimes change between OS versions, and may also have localized strings for different cultures.  My WMI-related posts are just to offer an alternative to people who would prefer to avoid these problems.

  • @David

    Love the work!  Nicely done!

    The key reason for my automating DISKPART was to automate the creation of Bootable USB keys.   To take the WMI solution one step further, it would be cool to see if we can either a) Create a Bootable USB key via WMI or b) Leverage the SAME data from WMI to create the DISKPART script.

    I'll have to play with your results this weekend.    This could be fun (Yes, I'm a geek. I think this is fun) :)

    Sean

  • Any chance anyone took this sample and got it to work for 2003, 2008 and 2008 r2?

    It fails to produce the same output obviously because diskpart data changes everytime the OS does.

  • DiskPart.exe - Powershell Parser for Windows Server 2008 R2
    https://gallery.technet.microsoft.com/DiskPartexe-Powershell-0f7a1bab