Provision and Build Windows VM's in a Hyper-V Lab Environment Using PowerShell and ConfigMgr

Background

I needed a way to efficiently provision and build Windows 10 systems in my Hyper-V lab environment which followed a naming convention. The obvious way forward was to create a series of PowerShell scripts. This post is to serve as an example of how to achieve this in a lab, in no way is this production ready.

Firstly a script is executed on the Hyper-V host to provision a new virtual machine with predefined settings for RAM, CPU etc plus it is set to boot from network. To ensure each VM has a unique hostname it is derived from today's date plus a portion of the network adapters MAC address.

My ConfigMgr environment has PXE enabled DP's with unknown computer support, so once the VM is booted it will load WinPE and I'll be presented with the list of available task sequences. During the task sequences another PowerShell script is run to populate the OSDComputerName TS variable with the same name as the VM. This is determined based on the same logic as the previous script (using today's date + MAC).

Hyper-V Provisioning

This script uses the Hyper-V cmdlets to set up a new VM, it's booted initially (start-vm) to generate the network adapter MAC address. This will need populating with your environment specific settings.

#retrieive today's date
$date = get-date -Format ddMM
#create prefix for Win10 systems
$prename = "W10-$date" 

New-VM -Name $prename -MemoryStartupBytes 4GB -BootDevice NetworkAdapter -SwitchName 'Location 2'  -Path K:\ConfigFiles -Generation 2
Start-VM $prename
Stop-VM $prename -TurnOff
$mac = Get-VMNetworkAdapter $prename
$mac = $mac.MacAddress
$mac = $mac.Substring($mac.get_Length() -4)
$name = "$prename-$mac"
Rename-VM -Name $prename -NewName $name
$path = New-VHD -Path K:\vhd\$name.vhdx -Dynamic -SizeBytes 40GB

Add-VMHardDiskDrive -ControllerType SCSI -VMName $name -Path $path.path
Set-VMProcessor $name -Count 2

ConfigMgr OSDComputerName

This script is run before the 'Apply Windows Settings' task sequence step in any TS that I'll be running. I've used the 'IsVM' variable to prevent this from executing on hardware (The serial number is used for hardware builds).

$tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment 
$TSComputerName = $tsenv.value("OSDComputerName") 

$date = get-date -Format ddMM
$prename = "W10-$date" 

$mac= Get-WMIObject Win32_NetworkAdapter -filter "AdapterType Like '%ethernet%'" | Select MacAddress
$mac = $mac.MacAddress
$mac = $mac -replace ':',''
$mac = $mac.Substring($mac.get_Length() -4)
$name = "$prename-$mac"
$TSComputerName = $name 
$tsenv.value("OSDComputerName") = $TSComputerName






About Me

My photo
Senior Consultant at CDW UK specialising in Microsoft workspace and cloud technologies.