Changing Hyper-V Configs in Powershell from CSV - variables generate errors

Anonymous
2021-10-28T02:39:32.043+00:00

I am trying to get a small script together that will change the resources on a series of VM's on a hyper-v host. I need to change the CPU count and the Memory allocation to whatever the variables are imported from the CSV. However, when I try to pull the variable for CPU and Memory, I get a series of errors. But if I change those variables to a number, they work just fine. Any help is greatly appreciated.

$VMList = Import-csv "C:\temp\vmspecs_test.csv"

foreach-object {
$VMName = $VMList.Name
$CPUCount = "4"
$MaxMemory = 1GB*("4")
Stop-VM -Name $VMName -Force
Set-VMProcessor $VMName -Count $CPUCount
Set-VMMemory $VMName -DynamicMemoryEnabled $false -StartupBytes $MaxMemory
Start-VM -Name $VMName
}

However, if I change "$CPUCount = $VMList.NewCPU" (which is just a column in csv with a numeric 4 in it), I get the error

"Set-VMProcessor : Cannot convert 'System.Object[]' to the type 'System.Nullable`1[System.Int64]' required by parameter 'Count'.
Specified method is not supported.
At C:\Users\Administrator\Documents\VirtualMachineResourceModification.ps1:10 char:32

  • Set-VMProcessor $VMName -Count $CPUCount
  • ~~~~~~~~~
  • CategoryInfo : InvalidArgument: (:) [Set-VMProcessor], ParameterBindingException
  • FullyQualifiedErrorId : CannotConvertArgument,Microsoft.HyperV.PowerShell.Commands.SetVMProcessor"

And if I change the value of $MaxMemory to $MaxMemory = 1GB*($VMList.MaxMem) OR [int64]$MaxMemory = 1GB*($VMList.MaxMem), it errors with

Method invocation failed because [System.Object[]] does not contain a method named 'op_Multiply'.
At C:\Users\Administrator\Documents\VirtualMachineResourceModification.ps1:8 char:1

  • $MaxMemory = 1GB*($VMList.MaxMem)
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • CategoryInfo : InvalidOperation: (op_Multiply:String) [], RuntimeException
  • FullyQualifiedErrorId : MethodNotFound

Can anyone please tell me what I am doing wrong? I have tried using a singular Set-VM option and ran into conversion of int32 and int64 errors. I have tried using a byte amount (no mathematical operator for memory, just 4294967296) and it still won't work from csv. I appreciate any help in advance.

Hyper-V
Hyper-V
A Windows technology providing a hypervisor-based virtualization solution enabling customers to consolidate workloads onto a single server.
2,560 questions
Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,389 questions
0 comments No comments
{count} votes

Accepted answer
  1. Eric Siron 1,251 Reputation points MVP
    2021-10-29T18:08:13.403+00:00

    The variables inside your foreach are not doing what you think they're doing.
    You defined $VMList as a list of virtual machines at the beginning.
    In line 4, $VMName is not the name of the currently foreach'd VM, but every single item in the "Name" column of your CSV. That doesn't break lines 7-10 because all of those will accept an array of names. Basically, you are running lines 7-10 for every single virtual machine on every pass of the foreach.
    Your changed line breaks because the Count parameter of Set-VMProcessor will not accept a list of numbers. $VMList.NewCPU represents a list of every single item in the "NewCPU" column of your CSV. That's what the 'System.Object[]' part of the error is trying to tell you.
    To reference the current item in a foreach loop, use $_. So, line 4 becomes:
    $VMName = $_.Name
    and your updated line becomes:
    $CPUCount = $_.NewCPU

    Edited to add:
    Also, your foreach does not have an input object, so it doesn't know what to foreach over. You can write the foreach line like this:
    ForEach-Object -InputObject $VMList -Process {

    Personally, I don't find the $_ syntax particularly legible and prefer to use the language construct foreach instead of the cmdlet. That would look something like:

    foreach ($VM in $VMList)
    {
    Stop-VM $VM.Name
    ...
    Start-VM $VM.Name
    }

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful