Interactive PowerShell Script for Hyper-V VM Provisioning

In this tutorial, I’ll be sharing my PowerShell script that simplifies the process of creating Hyper-V virtual machines (VMs) interactively. If you find yourself performing repetitive tasks for VM provisioning, this script will be a game-changer.

With the power of PowerShell automation, I’ve developed a script that allows you to dynamically configure VM settings, including naming, memory, virtual processors, virtual disk, network connectivity, and operating system. This interactive approach gives you the flexibility to customise each VM according to your needs.

                                                                                                         Short Demo

To list the network adapters, it is necessary to run PowerShell with administrator privileges. This ensures that the script can access the required information and display the network adapter details accurately. Make sure to launch PowerShell as an administrator to successfully retrieve and work with network adapter information.

Here is the actual PowerShell script that allows you to create Hyper-V VMs interactively. It is designed to be user-friendly and easily understandable, even for those new to PowerShell scripting. Without further delay, let’s explore the power of this script!

# Prompt user to enter the name of the machine
$vmName = Read-Host “Enter the name of the virtual machine”

# Create a new folder for the VM in D:\MyVMs
$vmFolderPath = “D:\MyVMs\$vmName          # D:\MyVMs\ – This Folder should already exist
New-Item -ItemType Directory -Path $vmFolderPath | Out-Null

# Prompt user to choose Generation 1 or 2
$generation = Read-Host “Choose the generation (1 or 2) for the virtual machine”

# Prompt user to choose the number of virtual processors
$numProcessors = Read-Host “Enter the number of virtual processors”

# Prompt user to enter the size of the VHD in GB
$vhdSize = Read-Host “Enter the size of the VHD in GB (Example 10)”

# Prompt user to choose the storage type (Dynamic or Fixed)
$storageTypeChoice = Read-Host “Choose the storage type for the VHD:
1. Dynamic
2. Fixed”

# Validate the storage type choice
while ($storageTypeChoice -ne “1” -and $storageTypeChoice -ne “2”) {
    Write-Host “Invalid choice. Please select 1 for Dynamic or 2 for Fixed.”
    $storageTypeChoice = Read-Host “Choose the storage type for the VHD:
    1. Dynamic
    2. Fixed”

# Convert the storage type choice to a boolean value
$isDynamic = ($storageTypeChoice -eq “1”)

# Set the path for the VHD based on the VM’s folder path
$vhdPath = Join-Path -Path $vmFolderPath -ChildPath $vmName.vhdx”

# Prompt user to choose RAM Memory in MB and select dynamic option
$ramMemory = Read-Host “Enter the RAM memory in MB”
$ramDynamic = Read-Host “Do you want the RAM to be dynamic? (Y/N)”

# Prompt user to choose whether Secure Boot should be enabled
$secureBootEnabled = Read-Host “Enable Secure Boot? (Y/N)”

# Convert the VHD size to bytes as Int64
$vhdSizeBytes = [Int64]$vhdSize * 1GB

# Convert the input to lowercase for comparison
$secureBootEnabled = $secureBootEnabled.ToLower()

# Prompt user to enter the number of switches to connect
$numSwitches = Read-Host “Enter the number of switches to connect”

# List all available switches in Hyper-V
$availableSwitches = Get-VMSwitch | Select-Object -Property Name

# Array to store the selected switches
$selectedSwitches = @()

# Prompt user to select the switches
for ($i = 1; $i -le $numSwitches; $i++) {
    Write-Host “Available switches:”
    $availableSwitches | ForEach-Object -Begin { $counter = 1 } {
        Write-Host $counter. $($_.Name)
    $choice = Read-Host “Select switch $i
    $selectedSwitch = $availableSwitches[[int]$choice1].Name
    $selectedSwitches += $selectedSwitch

# Create the VM with the specified configuration
New-VM -Name $vmName -Path $vmFolderPath -Generation $generation | Out-Null

# Set the number of virtual processors for the VM
Set-VMProcessor -VMName $vmName -Count $numProcessors

# Create the VHD with the specified size and storage type
if ($isDynamic) {
    New-VHD -Path $vhdPath -SizeBytes $vhdSizeBytes -Dynamic | Out-Null
} else {
    New-VHD -Path $vhdPath -SizeBytes $vhdSizeBytes -Fixed | Out-Null

# Add the virtual hard disk drive to the VM
Add-VMHardDiskDrive -VMName $vmName -Path $vhdPath | Out-Null

# Set the RAM memory for the VM
$ramMemoryBytes = [int]$ramMemory * 1MB
Set-VMMemory -VMName $vmName -DynamicMemoryEnabled ($ramDynamic -eq “Y”) -StartupBytes $ramMemoryBytes

# Connect the VM to the selected switches
foreach ($switch in $selectedSwitches) {
    Add-VMNetworkAdapter -VMName $vmName -SwitchName $switch

# Enable or disable Secure Boot based on user’s selection
if ($secureBootEnabled -eq “Y” -or $secureBootEnabled -eq “y”) {
    Set-VMFirmware -VMName $vmName -EnableSecureBoot On
else {
    Set-VMFirmware -VMName $vmName -EnableSecureBoot Off

# List all images in D:\myISO
$isoFolder = “D:\myISO”   # You need to have .iso Images already stored in this folder
$isoFiles = Get-ChildItem $isoFolder | Select-Object -Property Name

# Prompt user to choose an ISO file
Write-Host “Available ISO files:”
$isoFiles | ForEach-Object -Begin { $counter = 1 } {
    Write-Host $counter. $($_.Name)
$choice = Read-Host “Enter the number of the ISO file”
$selectedISO = $isoFiles[[int]$choice1].Name

# Set the path for the VHD based on the VM’s folder path
$vhdPath = Join-Path -Path $vmFolderPath -ChildPath $vmName.vhdx”

# Create a virtual DVD drive for the VM
Add-VMDvdDrive -VMName $vmName

# Configure the bootable image for the VM
Set-VMDvdDrive -VMName $vmName -Path $isoFolder\$selectedISO

# Get the DVD drive object
$dvdDrive = Get-VMDvdDrive -VMName $vmName

# Set the boot order to prioritize the DVD Drive
$bootOrder = @($dvdDrive.Id.ToString())
Set-VMFirmware -VMName $vmName -FirstBootDevice $dvdDrive #-BootOrder $bootOrder

# Add Checkmark
$symbols = [PSCustomObject] @{CHECKMARK = ([char]8730)

Write-host `n
Write-host ”          ————————————————–“
Write-Host ”          Virtual machine ‘$vmName‘ created successfully.   $($symbols.CHECKMARK)
Write-host ”          ————————————————–“
Write-host `n