Summary: Use the freely available Convert-WindowsImage.ps1 to extract multiple bootable VHD files for Hyper-V Server 2012 R2.
Hey, Scripting Guy!
Is there an easier way to create a VHD file that already has the operating system, rather than installing it and clicking Next…Next…Next? I’d like something that could spin up a simple machine like it was a template.
—JA
Hello JA,
Honorary Scripting Guy, Sean Kearney, is here. Funny you should ask. I was poking about with that idea the other day. I decided for a good simple lab, I would need the following:
- A blank preconfigured VHD file that I could copy for a virtual machine
- A domain controller that I could easily spin up
- An easy way to set up the machine name and basic settings on said virtual machines
- A simple way to edit and pass data
- A way to keep the costs low, including software
Ideally this solution, as I was thinking to myself, could even potentially leverage Windows Powershell Desired State Configuration in the long term. More importantly, I wanted something that could be simple enough that a person with minimal knowledge of Windows PowerShell could easily use to spin up machines.
I will make some important notes. Although this solution is targeted to use the free tools, it works equally well in the full versions of Windows Server 2012 R2 and Windows 8.1. It might work with Windows Server 2012, but I haven’t tested it yet. Theoretically, it should all work.
So a few pieces came together. For software, I opted for the following free tools from Microsoft and the IT community.
Free hosting environment for virtual machines from Microsoft | |
180-day trial of Windows Server 2012 R2 as an operating system for the virtual machines | |
Free script written by a Microsoft partner, Pronichkin, to directly convert a WIM file to a bootable VHD. This is a great tool! |
I’m going to presume that you at least know how to setup Hyper-V. If you download the free version, you’ll need to run sconfig to configure the environment. It is a really nice easy-to-use VBScript script that does all the nasty work. You’ll also have to remember that it defaults to Cmd.exe, and you will have to launch Powershell.exe to execute all of your scripts.
If you’re curious about trying to get a Hyper-V environment initially configured, here’s a series I wrote a while back on TechNet that will give you some tips: Hyper-V and the Windows PowerShell Cmdlets.
So with the presumption you have a server running Hyper-V, our first task is to get all those goodies out of the WIM file. I want to avoid typing anything as much as possible. I would also like the VHD files that I create to reflect the version of the server.
Within the latest Windows Server environments, there is a built-in cmdlet called Mount-DiskImage, which will allow us to mount either an ISO file or a VHD file directly from Windows PowerShell, and then access its contents.
$ISOFile=”C:\ISO\9600.16384.WINBLUE_RTM.130821-1623_X64FRE_SERVER_EVAL_EN-US-IRM_SSS_X64FREE_EN-US_DV5.ISO"
MOUNT-DISKIMAGE –imagepath $ISO
This is all good. But it doesn’t return the drive letter of the mounted VHD or ISO file. You can obtain this by using two other cmdlets, which we pipe together for this information:
GET-DISKIMAGE –imagepath $ISO | GET-Volume
If we need only the drive letter, we’ll access the property directly and store it away:
$DriveLetter=((GET-DISKIMAGE –imagepath $ISO | GET-Volume).DriveLetter)+”:”
Now with the drive letter in a scriptable state, we need to get some information about the WIM file. We need to know how many images are in the WIM file and the descriptions for each image. We will leverage this information when launching the Convert-WindowsImage.ps1 file.
To get this information, we can leverage the Get-WindowsImage cmdlet from the DISM module. We target the WIM file, and it will return a list of images, their index numbers, and descriptions for it:
GET-WINDOWSIMAGE –ImagePath ($DriveLetter+”\sources\install.wim”)
Now we’ll capture that information to make it useful by storing it away:
$Images=GET-WINDOWSIMAGE –ImagePath ($DriveLetter+”\sources\install.wim”)
This is where the fun begins. We’re going to make some bootable VHDs. The Convert-WindowsImage commandneeds to be provided only three pieces of information to make it useful:
- Location of the WIM file
- Index or name of the edition we want to extract
- Name and location to assign to the VHD file
A simple example of the script in action would be this:
CONVERT-WindowsImage.PS1 –sourcepath install.wim –VHDPath c:\vhds\filename.vhd –edition ServerDataCenterCore
Or if we’re going to specify the index number (same version here too):
CONVERT-WindowsImage.PS1 –sourcepath install.wim –VHDPath c:\vhds\filename.vhd –edition 3
We already know the name and location of the WIM file. Now we start up a nice FOR loop, step through the images:
FOREACH ($Image in $Images)
{
...and grab the index number:
$Index=$Image.Index
If only I could remove the spaces from the description and make that into a file name…
Oh, right! I’m in Windows PowerShell! I can! We’ll grab the description first:
$ImageDescription=$Image.ImageDescription
…and then use the Replace method to remove the spaces:
$ImageDescription=$ImageDescription.replace(“ “,””)
Then add our destination location and file extension to our new name:
$VHDName=”C:\ISO\”+$ImageDescription+”.VHD”
And with one-fell swoop, launch the script to create a bootable VHD from a WIM file entry:
C:\ISO\Convert-WindowsImage.PS1 –sourcepath “$Driveletter\Sources\Install.wim” –Edition $Index –VHDPath $VHDName
}
Save this file into a folder. In this post, I am referencing C:\ISO, which is where I wrote this environment from. Make that location and save it there for ease-of-use. I called my CREATE-VMTemplate.PS1.
Place the Convert-WindowsImage.ps1 and CREATE-VMTemplate.PS1 in this folder and execute CREATE-VMTemplate.PS1:
.\CREATE-VMTemplate.PS1
Watch…and in about 10 minutes (depending on the speed of your computer and hard disk), you’ll have a lovely pile of VHDs that look like this:
Come back tomorrow when we go to the next step and make an easier way to configure the VHD before attaching it to a virtual machine.
I invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then remember eat your Cmdlets each and every day with a taste dash of Creativity.
Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy