New Hyper-V VM via PowerShell or GUI

If you prefer video over written format the corresponding video for this write-up can be viewed below:

Here is all the PowerShell code required for the creation of a new Hyper-V VM.  The code below can be used to prompt for all needed settings to fully setup and configure a new Hyper-V VM.  This is a fully functional script that could be easily modified to spin up multiple VMs at once, or even import settings from a .csv or .txt file.  A full write-up with examples for the GUI can also be found below.

Create a New Hyper-V VM – PowerShell Method

#----------------USER CREATION QUESTIONS-------------------
[string]$vmName= Read-Host ”Name of VM”
#__________________________________________________________
[int32]$generation = Read-Host "Generation Type"
#__________________________________________________________
[string]$dynamic = $null
while("yes","no" -notcontains $dynamic){
    $dynamic = Read-Host "Will this VM use dyanmic memory? (yes/no)"
}
if($dynamic -eq "yes"){
    [bool]$dynMemory = $true
    [int64]$minMemory = Read-Host "Memory Minimum (MB)"
    [int64]$maxMemory = Read-Host "Memory Maximum (MB)"
    [int64]$startMemory = Read-Host "Starting Memory (MB)"
    #convert to bytes
    $minMemory = 1MB*$minMemory
    $maxMemory = 1MB*$maxMemory
    $startMemory = 1MB*$startMemory
    [int64]$memory = $minMemory
}
else{
    [int64]$memory = Read-Host "Memory (MB)"
    #convert to bytes
    $memory = 1MB*$memory
}
#__________________________________________________________
Write-Host "--------AVAILABLE SWITCHES--------" -BackgroundColor Black
Get-VMSwitch | Select-Object -ExpandProperty Name
Write-Host "--------AVAILABLE SWITCHES--------" -BackgroundColor Black
[string]$vmSwitch = Read-Host "Please enter a virtual switch name"
#__________________________________________________________
[int32]$cpu = Read-Host "Number of CPUs"
#__________________________________________________________
[string]$vmPath = Read-Host "Enter path for VM config files (Ex E:\VM\)"
[string]$newVMPath = $vmPath
#__________________________________________________________
[string]$vhdPath = Read-Host "Enter path where .vhdx will reside (Ex E:\VHD\)"
[string]$newVHD = $vhdPath+$VMName+".vhdx"
[int64]$vhdSize = Read-Host "Enter VHDSize (GB)"
$vhdSize = [math]::round($vhdSize *1Gb, 3) #converts GB to bytes
#__________________________________________________________

#----------------END USER CREATION QUESTIONS---------------

try{
    #-----------------CONFIRM CREATE NEW VM----------------
    Write-Host "Creating new VM:" $vmName "Generation type:" $generation `
        "Starting memory:" $memory "stored at:" $newVMPath ", `
            with its .vhdx stored at:" $newVHD "(size" $vhdSize ")" -ForegroundColor Cyan
    [string]$confirm = $null
    while("yes","no" -notcontains $confirm){
        $confirm = Read-Host "Proceed? (yes/no)"
    }
    #---------------END CONFIRM CREATE NEW VM--------------
    
    if($confirm -eq "yes"){
         #------------------CREATE NEW VM-----------------------
        NEW-VM –Name $vmName -Generation $generation –MemoryStartupBytes $memory `
            -Path $newVMPath –NewVHDPath $newVHD –NewVHDSizeBytes $vhdSize | Out-Null
        Start-Sleep 5 #pause script for a few seconds to allow VM creation to complete
        #----------------END CREATE NEW VM---------------------

        #---------------CONFIGURE NEW VM-----------------------
        ADD-VMNetworkAdapter –VMName $vmName –Switchname $vmSwitch
        #______________________________________________________
        Set-VMProcessor –VMName $vmName –count $cpu
        #______________________________________________________
        if($dynMemory -eq $true){
            Set-VMMemory $vmName -DynamicMemoryEnabled $true -MinimumBytes $minMemory `
                -StartupBytes $startMemory -MaximumBytes $maxMemory
        }
        Start-Sleep 8 #pause script for a few seconds - allow VM config to complete
        #---------------END CONFIGURE NEW VM-------------------
        #display new VM information
        Get-VM -Name $vmName | Select Name,State,Generation,ProcessorCount,`
            @{Label=”MemoryStartup”;Expression={($_.MemoryStartup/1MB)}},`
            @{Label="MemoryMinimum";Expression={($_.MemoryMinimum/1MB)}},`
            @{Label="MemoryMaximum";Expression={($_.MemoryMaximum/1MB)}} `
            ,Path,Status | ft -AutoSize
    }
    else{
        Exit
    }
   
}
catch{
    Write-Host "An error was encountered creating the new VM" `
        -ForegroundColor Red -BackgroundColor Black
    Write-Error $_
}

Create a New Hyper-V VM – GUI Method

1. Initiate the New Virtual Machine Wizard

Open Hyper-V Manager – virtmgmt.msc – right click your Hyper-V server – New – Virtual Machine…

Hyper-V Manager - New Virtual Machine

Hyper-V Manager – New Virtual Machine

2. Give your new VM Name and choose where to save the VM configuration files

Note: This is just the name of the VM as it will be displayed on the Hyp. This is not the hostname of the VM.

Hyper-V - New Virtual Machine Wizard - Specify Name and Location

Hyper-V – New Virtual Machine Wizard – Specify Name and Location

The New Virtual Machine Wizard will have a default location of where the VM configuration files will be stored.  There are several files associated with this location as you can see in the below example so make sure you are storing them in an appropriate location.

#get VM config file locations and VHD locations
$vm = Get-VM -Name VM01
$vm | Select-Object VMName,Path,ConfigurationLocation,SnapshotFileLocation,`
SmartPagingFilePath
Get-VHD -VMId $vm.ID | select Path
VMName                : VM01
Path                  : V:\VMs
ConfigurationLocation : V:\VMs
SnapshotFileLocation  : V:\VMs
SmartPagingFilePath   : V:\VMs

Path : V:\VHDs\VM01.vhdx

Notice that the location of the config files and VHD/VHDX files differ.
Note: The SnapshotFileLocation is defaulted to store at this location as well. Something to keep in mind!

If you wish you can change the default location that is populated in the wizard.  This can be accomplished through the Hyper-V Manager – Hyper-V Settings – Virtual Hard Disks and Virtual Machines.

Alternatively, you can run the following PowerShell code to change the default locations for Hyper-V VMs and VHDs:

#Set Default HYPER-V locations
SET-VMHOST -virtualharddiskpath $Script:vmVHDLocation\LocalVMs\VHDs
SET-VMHOST -virtualmachinepath $Script:vmVHDLocation\LocalVMs\VMs

3. Specify a VM Generation type

This is an important decision and one that is not easily changed later (in some cases it is impossible to change).  You may want to familiarize yourself with the differences between the two by referencing the following Technet articles on the subject:

Generation 2 Virtual Machine Overview

Deciding When To Use Generation 1 or Generation 2 Virtual Machines with Hyper-V

The general idea is that if you’re running Windows 8/8.1/2012/2012R2 or newer, you will be choosing Generation 2.

Anything older and you will be running Generation 1.

Hyper-V - New Virtual Machine Wizard - Specify Generation

Hyper-V – New Virtual Machine Wizard – Specify Generation

4. Specify the startup memory

This is one setting where you don’t get nearly as much control via the GUI.  Here are a couple of case scenarios to help explain this screen:

Hyper-V - New Virtual Machine Wizard - Assign Memory

Hyper-V – New Virtual Machine Wizard – Assign Memory

Scenario #1: Startup Memory – 1024MB – Dynamic Memory Unchecked

Startup Memory: 1GB Minimum Memory: 1GB, Max Memory: 1GB

Scenario #2: Startup Memory – 1024MB – Dynamic Memory Checked

Startup Memory: 1GB Minimum Memory: 1GB, Max Memory: 1024GB (the GUI default sets it to this)

To adjust these further you will have to wait until the VM is created, right click on the new VM – Settings – Memory

Hyper-V - New Virtual Machine Wizard - Configure Networking

Hyper-V – New Virtual Machine Wizard – Configure Networking

5. Create the virtual hard disk

Again, the Wizard will place this in the default location (which you can change) with a default 127GB .vhd/.vhdx file.  I find that typically this is too large and 60GB for a system drive is generally sufficient.

Hyper-V - New Virtual Machine Wizard - Connect Virtual Hard Disk

Hyper-V – New Virtual Machine Wizard – Connect Virtual Hard Disk

6. Determine how you will install the OS

Here you get an opportunity to either defer the OS installation to a later time, or to immediately configure it for ISO boot or PXE boot.

Hyper-V - New Virtual Machine Wizard - OS Installation Options

Hyper-V – New Virtual Machine Wizard – OS Installation Options

7. Confirm settings and create VM

Hyper-V - New Virtual Machine Wizard - Summary

Hyper-V – New Virtual Machine Wizard – Summary

4 Responses

  1. Jason says:

    Brilliant! Thank you. I will certainly be using this going forward.

  2. John says:

    Just came across this while re-creating my own script. You’ve implemented a lot of the changes I was going to make and some extras so thanks for doing the legwork and sharing, you just saved my a morning of scripting… One simple thing I added at the end promotes the VM to a
    cluster role. Just added it the the very end.

    Get-VM -Name $vmName | Add-ClusterVirtualMachineRole

  3. RavanTharan says:

    thanks, for the wonderful script, just 1 question as to why there are 2 network adapters are being created

  4. Terry Chan says:

    Thank you! This is what I wanted. However, I’ve been running into something like this after running your code:
    “`
    Cannot bind parameter ‘Generation’. Cannot convert value “â€NewVHDPath C:\Users\YChan14\Documents\hyper-v\vhd\testVM.vhdx â€NewVHDSizeBytes” to type “System.Int16”. Error: “Input string was not in a correct format.”
    “`

    Do you have any idea why this is happening?

Leave a Reply

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