Author Posts

May 6, 2014 at 12:47 am

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.

May 6, 2014 at 3:34 am

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
    }
}

May 6, 2014 at 3:53 am

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

May 6, 2014 at 3:58 am

No problem, happy to help! 🙂

May 10, 2014 at 10:51 am

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!!!