Hyper-V HomeLab Intro

So  I’ve been playing with Hyper-V for a while now.  If you recall it was one of my 2016 goals to build a virtualization lab.

I’ve done that, building out the base Microsoft Test Lab Guide several times:

  • Manually (clicking in the GUI)
  • Using PowerShell commands (contained in the guides)
  • Using Lability and PS-AutoLab-Env

I was also fortunate enough to be a technical development editor for Learn Hyper-V in a Month of Lunches, which should be released this fall.

One thing that I’ve found is that being able to spin up a VM quickly is really nice.  With the Hyper-V cmdlets, that’s pretty easy.

Spinning up a machine from scratch and building a bootable image is not as easy.  Fortunately there are some tools to help.

In this post, I’m going to share a simple function I’ve written to help me get things built faster.

The goal of the function is to take the following information:

  • Which ISO to use
  • Which edition from the ISO to select
  • The Name of the VM (and VHDX)
  • How much memory
  • How many CPUs

With that information, it converts the windows image from the ISO to a VHDX, creates a VM with the right specs and using the VHDX, sets up the networking (or starts to, anyway), and starts the VM.

The bulk of the interesting work is done by Convert-WindowsImage, a function that pulls the correct image from an ISO and creates a virtual disk.

There are some problems with that script (read the Q&A on the Technet site and you’ll see what I mean).  The main one is when it tries to find the edition you ask for (by number or name).  The code is in lines 4087-4095, and should look like this:

                $Edition | ForEach-Object -Process {

                    $Edtn = $PSItem
                    if ([Int32]::TryParse($Edtn, [ref]$null)) {
                        $openImage = $openWim[[Int32]($Edtn)]    
                    } else {
                        $openImage = $openWim[$Edtn]

There’s a more recent copy of the function on github, but it has slightly different parameters and seems to be stale as well (according to the page it’s on). I’ve got an email out to find the “live” version.

With that, here’s my function:

function new-BootableVM {
    param($ISOPath = 'E:\isos\2012R2_x64_EN_Eval.iso',

    $switch = 'LabNet'
    $vhdpath = "c:\users\Public\Documents\Hyper-V\Virtual hard disks\$name.vhdx"

    Convert-WindowsImage -SourcePath $ISOPath -Edition $edition -VHDPath $vhdpath -VHDFormat VHDX -VHDType Dynamic -SizeBytes 8GB 
    $vm = New-VM -Name $name -MemoryStartupBytes ($memoryInGB * 1GB) -VHDPath $vhdpath -Generation 2 
    Set-VMProcessor -VM $vm -Count $vCPUs
    Add-VMNetworkAdapter -vm $vm -SwitchName $switch

    if (!$stopped) {
        Start-VM -VM $vm

Once the function is done running (assuming it didn’t have any issues), a VM will be created and ready for you. You will need to accept the license, set the locale, and set the administrators password, but that only takes a minute. I’ll be adding functions (or adding to this function) to take care of those as well as things like renaming the guest, joining a domain, copying files to the drive, etc.

It’s still a work in progress, so you will see some hardcoded values. Hopefully you can see what’s going on and adapt it to your needs.

I’ll be writing more as I play more with Hyper-V, DSC, and containers.

Let me know what you think



  1. Pingback: PowerShell Hyper-V HomeLab intro - How to Code .NET

  2. Hi Mike,

    My name is Anuj Agarwal. I’m Founder of Feedspot.

    I would like to personally congratulate you as your blog PowerShell Station – Mike’s PowerShell Musings has been selected by our panelist as one of the Top 50 PowerShell Blogs on the web.


    I personally give you a high-five and want to thank you for your contribution to this world. This is the most comprehensive list of Top 50 PowerShell Blogs on the internet and I’m honored to have you as part of this!

    Also, you have the honor of displaying the badge on your blog.


Leave a Reply

Your email address will not be published. Required fields are marked *