Building a working foreach loop on Get-VM

12,609

Solution 1

After spending some time with the code over the weekend, I started by removing all the user initiated variables and running a number of Write-Host. What I found was that the foreach and the inner for loops were running successfully, but the naming convention on the path was recycling, thus eliminating it from working 100%. The fix was simply to put the VM name variable in the pathway. Once that was done, it worked like a charm.

Here's the finished code:

Write-Host "This script is set up for quickly creating and initilizing VHDs"
$Path = "E:\Hyper-V\Virtual hard disks\Test Drives\"
$fileName = "target"
$vhdSize = 7GB

$GetVM = Get-VM -ComputerName localhost
Foreach ($vm in $GetVM)
{
$n = $vm.Name
$vmAmount = 4
Write-Host "vm = " $n
For($val = 0; $val -le $vmAmount; $val++)
    {

      Write-Host "drive = " $val

      Write-Host "Path Before = " $Path

      $vhdPath = (Join-path $Path  ($n + "_" + $fileName + '-' + $val + '.vhdx'))

      Write-Host "Path after = " $vhdPath

      New-VHD -Path $vhdPath -SizeBytes $vhdSize -Fixed 
      Mount-VHD -Path $vhdPath
      $disk = get-vhd -path $vhdPath
      Initialize-Disk $disk.DiskNumber
      $partition = New-Partition -AssignDriveLetter -UseMaximumSize -DiskNumber $disk.DiskNumber
      $volume = Format-Volume -FileSystem NTFS -Confirm:$false -Force -Partition $partition
      Dismount-VHD -Path $vhdPath
      Add-VMHardDiskDrive -VMName $n -Path $vhdPath
    }        
}

Solution 2

Move the $val = 0 to just before the Foreach loop. Otherwise, although you increment at the end of the loop, at the start of the loop you are zeroing it again, so $val is always going to be zero.

Share:
12,609
Gavin_Talyn
Author by

Gavin_Talyn

I started with Geocities a long time ago. During the course of my career I got side tracked into hardware, networking, databases, and then accounting. Lately I've been wanting to come back to the coding side of things and found things much changed since I left in 2008. I'm attempting to rectify that and make a proper coder out of me.

Updated on June 04, 2022

Comments

  • Gavin_Talyn
    Gavin_Talyn almost 2 years

    I'm trying to build a loop that will take the Get-VM cmdlet, put it into an array, and let me run a foreach statement on each VM. When I have that array built, the loop should go to each VM, build the designated amount of VHDs, initialize them, format them, and attach them to the VM.

    The logic in the script works. It will build a disk and attach it to the VM. Where I'm failing is that the script will error out saying that the machine it is trying to build is already created (I suspect a scope error in my $val variable). It will also stop and not move to the next object.

    I suspect I have scope errors, and also that ForEach-Object might be a better way to go on this script. However at this point I'm lost and need a little help.

    As always, thank you and happy coding!

    Write-Host "This script is set up for quickly creating and initilizing VHDs"
    $Path = Read-Host "Please enter the path you want to create the drives to. Use the format in this example <E:\VHDS\>"
    $fileName = Read-Host "The Drive will be <target>-<number>.vhdx.  Please Name the target "
    $vhdSize = 1GB
    $vmAmount = 1
    
    $GetVM = Get-VM
    
    Foreach ($vm in $GetVM)
    {
        $n = $vm.Name.ToString()
        $val = 0
        For($internalCounter = 0; $internalCounter -le $vmAmount; $internalCounter++)
            {
                $vhdPath = (Join-path $Path  ($fileName + '-' + $val + '.vhdx'))
                New-VHD -Path $vhdPath -SizeBytes $vhdSize -Fixed 
                Mount-VHD -Path $vhdPath
                $disk = get-vhd -path $vhdPath
                Initialize-Disk $disk.DiskNumber
                $partition = New-Partition -AssignDriveLetter -UseMaximumSize -DiskNumber $disk.DiskNumber
                $volume = Format-Volume -FileSystem NTFS -Confirm:$false -Force -Partition $partition
                Dismount-VHD -Path $vhdPath
                Add-VMHardDiskDrive -VMName $n -Path $vhdPath
            }
         $val++
    }