Mass create VMs with script

Hello,

I managed to write a script that creates a VM with all the memory, VHD, DVD drive and other settings.
This arrangement works awesome if I create VMs one at a time, but how can I create several VMs with this one script?

[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$VMName,
[Parameter(Mandatory=$true)]
[string]$SwitchName,
[Parameter(Mandatory=$true)]
[string]$ISOPath
)

New-VM -Name $VMName -MemoryStartupBytes 512MB -Generation 2 -Path C:\VM -SwitchName $SwitchName
New-VHD -Path C:\VHD$VMName.vhdx -SizeBytes 40GB -Dynamic
Set-VMMemory -VMName $VMName -DynamicMemoryEnabled $true -MinimumBytes 512MB
Add-VMHardDiskDrive -VMName $VMName -Path C:\VHD$VMName.vhdx
Add-VMDvdDrive -VMName $VMName -Path $ISOPath

If I set the $VMName parameter to accept several values like [string]$VMName, I get the error “… Cannot convert ‘System.String’ to the type ‘System.String’ required by parameter ‘Name’…”.

The idea is that I’d like to create several VMs by only feeding in a list of VM names, setting the same ISO path and virtual switch for all of them with one script.

You can change your code like this, to accept multiple VM names (though they’ll still be created one at a time, at least you only have to call your function once to do the whole batch):

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true, ValueFromPipeline = $true)]
    [string[]]
    $VMName,

    [Parameter(Mandatory=$true)]
    [string]
    $SwitchName,

    [Parameter(Mandatory=$true)]
    [string]
    $ISOPath
)

process
{
    foreach ($name in $VMName)
    {
        New-VM -Name $name -MemoryStartupBytes 512MB -Generation 2 -Path C:\VM -SwitchName $SwitchName
        New-VHD -Path C:\VHD\$name.vhdx -SizeBytes 40GB -Dynamic
        Set-VMMemory -VMName $name -DynamicMemoryEnabled $true -MinimumBytes 512MB
        Add-VMHardDiskDrive -VMName $name -Path C:\VHD\$name.vhdx
        Add-VMDvdDrive -VMName $name -Path $ISOPath
    }
}

Thank you very much Mr Wyatt, you helped me learn a lot! Exactly this is what I was trying to figure out!

No problem, happy to help! :slight_smile:

Foreach is AMAZING! It seems you can do just anything with it! I managed to automate changing the default boot order and included it in the script!
Now it not only creates multiple VMs with all the desired settings, but also sets the boot order to boot from the ISO image right away!
I’m so happy I can’t tell you!
I post it here, maybe it’ll benefit other PowerShell learners too:


[CmdletBinding()]
param(
    [Parameter(Mandatory=$true, ValueFromPipeline = $true)]
    [string[]]
    $VMName,

    [Parameter(Mandatory=$true)]
    [string]
    $SwitchName,

    [Parameter(Mandatory=$true)]
    [string]
    $ISOPath
)

process
{
    foreach ($name in $VMName)
    {
        New-VM -Name $name -MemoryStartupBytes 512MB -Generation 2 -Path C:\Lab\VM -SwitchName $SwitchName
        New-VHD -Path C:\Lab\VHD\$name.vhdx -SizeBytes 40GB -Dynamic
        Set-VMMemory -VMName $name -DynamicMemoryEnabled $true -MinimumBytes 512MB
        Add-VMHardDiskDrive -VMName $name -Path C:\Lab\VHD\$name.vhdx
        Add-VMDvdDrive -VMName $name -Path $ISOPath

        $firmware = Get-VMFirmware -VMName $name
        $network = $firmware.bootorder[0]
        $vhd = $firmware.bootorder[1]
        $dvd = $firmware.bootorder[2]

        Set-VMFirmware -VMName $name -BootOrder $dvd,$network,$vhd
    }
}

Thanks a lot again!!!