Learn about Windows PowerShell
Summary: Honorary Scripting Guy, Sean Kearney, talks about using Windows Powershell to build scripts to automate DiskPart.
Hey, Scripting Guy! I know I can create a bootable USB key by using DiskPart, but is there any way to have it automated so the computer does the work for me?
Honorary Scripting Guy, Sean Kearney, here. I’m filling in for our good friend, Ed Wilson, who’s building some giant contraption in his backyard to hold his giant collection of bow ties. So he’s a bit “tied up.”
So the answer is absolutely, “Yes! Yes! Yes!” You can automate the creation of bootable memory keys. Having this ability is great if you’re using utilities like MDT 2012, and you need bootable media on the fly.
So I sat down and poked through my shiny new Surface Pro to dig for cmdlets to automate creating bootable partitions on USB. There are so many new modules and cmdlets to choose from.
Then my jaw dropped. There were none (at least none that I could spy), and I wanted to fix that.
Creating a bootable USB key is pretty easy. Most of us could run this process with our hands behind our backs while singing a happy tune. The standard procedure for a bootable USB key is:
So if your USB key always came up as DISK 2, you might have a little text file called “bootme.txt” with the following commands:
You could happily run:
DISKPART /s .\bootme.txt
….and whoosh! All done.
But wouldn’t it be far nicer to have something a bit more dynamic with the ability to figure out most of the work for you? Then you actually could do this with a touch of your fingers!
The ironic thing about DiskPart is that it works great, but it doesn’t have a native way to export the information it has.
But I know of something that can help. Wait for it…
Starts with a “P”…
Has a cool theme song…
Yes! Of course! PowerShell can aid here! We can actually have Windows PowerShell create scripts for DiskPart and leverage the output of DiskPart to create newer scripts for it!
Sounds like magic doesn’t it? Nope. Just a feature of Windows PowerShell that has been used before to automate applications like HANDLE.exe from Sysinternals.
So our first challenge is to create a text file for DiskPart to literally “List the disks.”
We could cheat and simply type something in Notepad, but if we use a script (or better yet, build a function), the solution will be self-contained.
So first—oh mighty PowerShell—make me a text file. We could do something really fancy and elegant, but sometimes simplicity is best. Simple means easy to modify and easy to understand. Here we go:
NEW-ITEM –name listdisk.txt –itemtype file –force | OUT-NULL ADD-CONTENT –path listdisk.txt “LIST DISK”
Now we can automate DiskPart with this new mini script. But we’ll want to capture the output:
$LISTDISK=(DISKPART /S LISTDISK.TXT)
So what we’ve done here is capture all the output DiskPart was sending to the screen as a Windows PowerShell object. Now we can do all sorts of really neat stuff—like parse the data for what we want.
So the first thing we need to know from “LIST DISK” is, well, how many disks we’re looking at. Believe it or not, this is easier than you imagine. First off, the number of lines in the output is a built-in property:
Now there are a lot of funky ways to figure this out. But honestly, all we have to know is how many of the lines in the output do not contain the information we want—the lines with the disk information. That number happens to be 9. (Yes, I smudged up my screen and counted 1….2…..3….ketchup stain.)
So we can use Windows PowerShell to calculate this:
But we have a ways to go. We need to find out the assigned number for the drive if it’s a USB flash drive…whether it’s pink or green.
But we’ll come back tomorrow and show more about how we can parse the information from DiskPart!
I invite you to follow us on Twitter and Facebook. If you have any questions, send email to Ed at firstname.lastname@example.org, 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
'select disk 0',
$commands | diskpart
$results = $commands | diskpart
Very cool! An excellent example of improving upon the original solution!
I apologize if this winds up being a duplicate post. I typed it out and submitted once before, and it's not showing up.
It might not be very reliable to parse diskpart's text output as a way of reading the list of disks. Different versions of diskpart (or different localizations) might format the output differently, causing headaches (essentially the whole reason PowerShell works with Objects instead of text).
It looks like the WMI class Win32_DiskDrive might provide a cleaner alternative. I've run the "list disk" command on a few different computers (just Windows 7 and 2008 R2 so far, so it probably needs more thorough testing), and the "Index" property of Win32_DiskDrive appears to match the disk number in diskpart's output. If this is always the case, you also get the benefit of being able to filter based on the other properties of Win32_DiskDrive (InterfaceType and MediaType) to distinguished the removable USB drive from other types of disks.
Driving DISKPART in a pipeline has been around for a decade or more. It has been used in batch files and still works in PowerShell.
The primary use of DISKPART is not to list disk information although it can be used this way. It is useful for structuring or re-structuring existing and new disks. With tools like MDT diskpart has become less used but I see that many still like to use it. Ed's example with PowerShell shows how we can continue to use it with PowerShell.
If you only want disk partition information WMI is probable easier and more PosHy but does not work well inpre-Vista systems.
One more tool and two ways to use it with PowerShell.
The reason for utilizing DiskPart and PowerShell was to mimick the solution for making a bootable USB with Diskpart. But I absolutely love that this generating other ideas :)
The intended use of this particular solution is more for a single O/S but can be adapted. But you are correct in that there is always a chance the output might night be as consistent in some cases. Here is where Regular expressions might come into play.
Some techniques are not always obvious which is why I love doing these posts. People like yourself pop in with some great ideas to share.
Alone we cannot know all. Sharing our knowledge and working together we can solve anything
Yes - exploring many techniques is a good exercise which is why I am waiting t see your implementation of RegEx. Everyone does it differently and I always learn. This one does not have an obvious best solution.
No Regex this time but perhaps that in itself could be a cool blog post. If you're interested in PowerShell and Regular Expressions search for posts by PowerShell MVP Tome Tanasovski who makes Regex as easy as a one liner
@Sean - I can RegEx that but wanted to see how you would do it. I had an idea you might have an easier way. RegEx is the best and easiest way t 'objectify' the disk data from diskpart. The reason I know about using th4 pipe into diskpart is because I did this back in PosH v1. It was a good exercise for using PowerShell and RegEx
You need to clean your screen again.
$LISTDISK=(DISKPART /S LISTDISK.TXT)
This will not give you the correct number of disks listed, the output is different when you run diskpart with a diskpart script. The command "List disk" and the blank line after it is not shown and thus the number of lines to discard is 2 less, and should be 7.