my personal blog about systemcenter

Create mutiple VM from powershell in Hyper-V 2016 and powershell direct

For our test enviroment / playground i needed to create 400 domain joined Windows 2016 TP4 Servers , this being a enviroment without systemcenter i needed a helping hand in creating the VM’s as i didnt have Virtual Machine Manager or Configuration Manager ready

This is not a pretty script , uses write-host and odd loops to work around my lack of powershell skills , also uses hardcode credentials but will try to make it pretty later

The script creates the VM from a master template , renames and domain join though powershell direct , there is no error handling so it will sit and wait forever for powershell direct input if something goes wrong

Feel free to use and or laugh Smile and thank you to Charbel for his parameter syntax

Right now it just creates the VM ‘s under a CSV but does not cluster enable them

comments at [email protected]

#Demo Script to deploy Sequencial VM off a base template
#Script parts from

$Howmany = 100

$domain = “”

$localCred = new-object -typename System.Management.Automation.PSCredential `
  -argumentlist “Administrator”, (ConvertTo-SecureString “addpassword” -AsPlainText -Force)

$domainCred = new-object -typename System.Management.Automation.PSCredential `
  -argumentlist “Fabric\Administrator”, (ConvertTo-SecureString “asspassword” -AsPlainText -Force)

function rebootVM([string]$VMName) { Write-Output “[$($VMName)]:: Is Rebooting”; stop-vm $VMName; start-vm $VMName }

function waitForPSDirect([string]$VMName, $cred)
  Write-Output “[$($VMName)]:: Waiting for PowerShell Direct (using $($cred.username))”
  while ((Invoke-Command -VMName $VMName -Credential $cred -ScriptBlock { “Test” } -ea SilentlyContinue) -ne “Test”) { Sleep -Seconds 1 }

1..$Howmany | % {

$VMName = “WS2016-VM00$_”

Write-Host “Create VM $VMName” -BackgroundColor Black -ForegroundColor White

New-VHD -Path “C:\ClusterStorage\Volume1\$VMName\$VMName.vhdx” -ParentPath “C:\ClusterStorage\Volume1\BASEVHD\VMServerBase.vhdx” -Differencing

New-VM -Name $VMName -MemoryStartupBytes 1GB -SwitchName VM -Path C:\ClusterStorage\Volume1\$VMName -Generation 2

Set-VM -Name $VMName -DynamicMemory -MemoryMaximumBytes 2GB -MemoryMinimumBytes 512MB -ProcessorCount 2

Add-VMHardDiskDrive -VMName $VMName -ControllerType SCSI -ControllerNumber 0 -Path “C:\ClusterStorage\Volume1\$VMName\$VMName.vhdx”

Set-VM -VMName $VMName -AutomaticStopAction ShutDown

start-vm $VMName

1..$Howmany | % {

$DCGuestOSName = “WS2016-VM00$_”
$VMName = “WS2016-VM00$_”

# Set IP address, rename guest
  Write-Output “[$($VMName)]:: Starting Config  ”
  waitForPSDirect $VMName -cred $localCred
  Invoke-Command -VMName $VMName -Credential $localCred -Scriptblock {
  param ($VMName, $DCGuestOSName,$IPNumber,$subnet,$ip,$ipnum)

Write-Output “[$($VMName)]:: Prepare Network  “
  Rename-NetAdapter -InterfaceDescription “Microsoft Hyper-V Network Adapter” -NewName “ACCESS”

  Write-Output “[$($VMName)]:: Renaming OS to `”$($DCGuestOSName)`””
  Rename-Computer -NewName $DCGuestOSName

} -ArgumentList $VMName, $DCGuestOSName,$subnet,$IpNumber,$IP

  rebootVM $VMName
  waitForPSDirect $VMName -cred $localCred

#Domain Join
  Write-Output “[$($VMName)]:: Domain Join to  `”$($domain)`””
  Invoke-Command -VMName $VMName -Credential $localCred -Scriptblock {
  param ($domaincred,$domain)
  Add-Computer -DomainName $domain -Credential $domaincred

  } -ArgumentList $domaincred,$domain
  rebootVM $VMName