0

I've created a basic script to quickly add a VM in Hyper-V and everything works great until it reaches the Set-VMMemory command. At this point the variables seem to fail and generate an error.

Script code:

$Name = Read-Host -Prompt 'New VM Name'
$ProcessorCount = Read-Host -Prompt 'Processor Count'
$MinimumBytes = Read-Host -Prompt 'Dynamic Memory Minimum'
$MemoryStartupBytes = Read-Host -Prompt 'Memory Startup Bytes'
$MaximumBytes = Read-Host -Prompt 'Dynamic Memory Maximum'
$Priority = Read-Host -Prompt 'Dynamic Memory Priority'
$Buffer = Read-Host -Prompt 'Dynamic Memory Buffer'
$VlanId = Read-Host -Prompt 'VLAN ID'

New-VM -Name "$Name" -Path H:\VM –NewVHDPath H:\VHD\$Name\$Name.VHDX -NewVHDSizeBytes 64GB -SwitchName "INFRASTRUCTURE"
Set-VM -Name "$Name" -ProcessorCount "$ProcessorCount"
Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes $MinimumBytes -StartupBytes $MemoryStartupBytes -MaximumBytes $MaximumBytes -Priority $Priority -Buffer $Buffer
Set-VMNetworkAdapterVlan –VMName "$Name" –Access –VlanId "$VlanId"

Error code:

Set-VMMemory : 'test' failed to modify device 'Memory'. (Virtual machine ID 17109661-11E1-4213-97DA-19C5847C8F87)
Invalid startup memory amount assigned for 'test'. The minimum amount of memory you can assign to this virtual machine is '32' MB. (Virtual machine ID 17109661-11E1-4213-97DA-19C5847C8F87)
A parameter that is not valid was passed to the operation.
At line:12 char:1
+ Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes $MinimumBytes -St ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (Microsoft.HyperV.PowerShell.VMTask:VMTask) [Set-VMMemory], VirtualizationOperationFailedException
+ FullyQualifiedErrorId : InvalidParameter,Microsoft.HyperV.PowerShell.Commands.SetVMMemoryCommand

I've tried changing up the syntax but end up with the same or similar results. Any insight as to where the wheels are falling off that can be provided would be greatly appreciated.

CORRECTED SCRIPT WITH A FEW DEFAULT VALUE OPTIONS ADDED: Thanks again @Peter Hahndorf for pointing me in the right direction.

$Name = Read-Host -Prompt 'New VM Name'
$ProcessorCount = Read-Host "Processor Count (Press [Enter] to choose 2): "
    if ($ProcessorCount -eq ""){$ProcessorCount="2"} ; if ($ProcessorCount -eq $NULL){$ProcessorCount="2"}
[long]$MinimumBytes = Invoke-Expression (Read-Host -Prompt 'Dynamic Memory Minimum')
[long]$MemoryStartupBytes =  Invoke-Expression (Read-Host -Prompt 'Memory Startup Bytes')
[long]$MaximumBytes =  Invoke-Expression (Read-Host -Prompt 'Dynamic Memory Maximum')
[long]$VHDiskSize =  Invoke-Expression (Read-Host -Prompt 'VHDX Size')
$Priority = Read-Host "Dynamic Memory Priority (Press [Enter] to choose 50): "
    if ($Priority -eq ""){$Priority="50"} ; if ($Priority -eq $NULL){$Priority="50"}
$Buffer = Read-Host "Dynamic Memory Buffer (Press [Enter] to choose 20): "
    if ($Buffer -eq ""){$Buffer="20"} ; if ($Buffer -eq $NULL){$Buffer="20"}
$VlanId = Read-Host "Select Vlan ID (Press [Enter] to choose 2): "
    if ($VlanId -eq ""){$VlanId="2"} ; if ($VlanId -eq $NULL){$VlanId="2"}
New-VM -Name "$Name" -Path H:\VM –NewVHDPath H:\VHD\$Name\$Name.VHDX -NewVHDSizeBytes $VHDiskSize -SwitchName "INFRASTRUCTURE"
Set-VM -Name "$Name" -ProcessorCount "$ProcessorCount"
Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes "$MinimumBytes" -StartupBytes "$MemoryStartupBytes" -MaximumBytes "$MaximumBytes" -Priority "$Priority" -Buffer "$Buffer"
Set-VMNetworkAdapterVlan –VMName "$Name" –Access –VlanId "$VlanId"
Confusias
  • 148
  • 11
  • Static size entries work just fine: `Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes 2GB -StartupBytes 4GB -MaximumBytes 8GB` – Confusias Jul 15 '16 at 21:07
  • I've tried adding the memory sizes in MB and GB... `Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes '($MinimumBytes + "GB")' -StartupBytes '($MemoryStartupBytes +"GB")' -MaximumBytes '($MaximumBytes + "GB")' -Priority $Priority -Buffer $Buffer` **results in** `Set-VMMemory : Cannot bind parameter 'MinimumBytes'. Cannot convert value "($MinimumBytes + "GB")" to type "System.Int64". Error: "Input string was not in a correct format." At line:13 char:64 + Set-VMMemory "$Name" -DynamicMemoryEnabled $true -MinimumBytes '($MinimumBytes + ...` – Confusias Jul 15 '16 at 21:10
  • Looks like it works when I enter bytes into the variables: `Dynamic Memory Minimum: 2147483648` `Memory Startup Bytes: 4294967296` `Dynamic Memory Maximum: 8589934592` Obviously this is not ideal. Being able to enter the variable values in GB or even MB would be best.. – Confusias Jul 15 '16 at 21:38

1 Answers1

3

When using Read-Host you are getting a string and the KB/GB operator are not handled in the same way as when an integer is expected. You need to convert your input to an integer like:

 [int]$MinimumBytes = Invoke-Expression (Read-Host -Prompt 'Dynamic Memory Minimum')
 [int]$MemoryStartupBytes =  Invoke-Expression (Read-Host -Prompt 'Memory Startup Bytes')
 [int]$MaximumBytes =  Invoke-Expression (Read-Host -Prompt 'Dynamic Memory Maximum')

I hardly ever use Read-Host, script parameters are much more powerful for getting user input and you wouldn't have problems like this one.

At the beginning of your script you have:

 param(
     [parameter(Mandatory=$true)]
     [string]$Name,
     [int]$ProcessorCount = 2,
     [long]$MinimumBytes = 512MB
     ...
 )

You would then call the script like this:

ScriptName.ps1 -Name "new VM" -ProcessCount 4

Parameters can be very helpful, more info at TechNet: about_Parameters and about_Functions_Advanced_Parameters

Peter Hahndorf
  • 14,058
  • 3
  • 41
  • 58
  • Cheers, got it in one.. Had to make a minor adjustment for 64bit integer, but that was easy enough once you pointed me in the right direction. – Confusias Jul 16 '16 at 17:54
  • I'm new to this, is there some documentation on using script parameters you could point me to? – Confusias Jul 16 '16 at 18:08