Author Posts

September 20, 2016 at 10:41 am

Hi

I'm trying to list all snapshots on each host and though a hashtable would be the way to go. I've come up with this:

Clear-Host
$Output = @{}
$VMHosts = Get-VMHost -ComputerName S1, S2, S3, S4, S5, S6

ForEach ($VMHost in $VMHosts.Name) {
    $VMS = Get-VMSnapshot -VMName * -ComputerName $VMHost
    ForEach ($VM in $VMS) {
        $Output.Add{Server = $VMHost} #, $VM.VName, $VM.Name,$VM.SnapshotType
    }
}

I want to see something like:

Server   VMName               Name                                   SnapshotType
S1       Centos.FogServer05    Centos.... - (16/08/2016 - 09:53:55)  Standard

but I am getting this error:

Cannot find an overload for "Add" and the argument count: "1".
At D:\Scripts\VMs\Get-SnapshotByServer.ps1:8 char:9
+         $Output.Add{Server = $VMHost} #, $VM.VName, $VM.Name,$VM.Snap ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

What am I missing?
Thanks
Tony

September 20, 2016 at 11:44 am

$output.add('server','vmhost')

September 20, 2016 at 11:48 am

Note: A pscustomobject is easier to deal with multiple properties.

[pscustomobject]@{

server = $vmhost
name = $name
snapshot = $snapshot
etc = '...'

}

September 20, 2016 at 12:49 pm

As Dan mentioned you probably want to do something like below:

Clear-Host
$Output = @{} # this creates a hashtable
# I believe what you actually want is an array of hashtables to collect your information

# For performance reasons it is best to use the ArrayList class instead of just @() because it can grow 
# dynamically added without creating a new copy in-memory everytime an items is being added. 
# You can use your favorite search engine to find a comparison between @() and ArrayList.
$Output = New-Object -TypeName 'System.Collections.ArrayList'
$VMHosts = Get-VMHost -ComputerName S1, S2, S3, S4, S5, S6

ForEach ($VMHost in $VMHosts.Name) {
    $VMS = Get-VMSnapshot -VMName * -ComputerName $VMHost
    ForEach ($VM in $VMS) {

        $SnapshotInfo = [PSCustomObject]@{
            Server = $VMHost
            VMName = $VM.VMName
            Name = $VM.Name
            SnapshotType = $VM.SnapshotType
        }

        $Output.Add($SnapshotInfo)
    }
}

September 20, 2016 at 12:58 pm

Another way to try is a calculated property and avoid all of the for loops:

$results = Get-VMHost -ComputerName S1, S2, S3, S4, S5, S6 |
           Select *, @{Name="Snapshots";Expression={Get-VMSnapshot -VMName * -ComputerName $_.Name}}

September 20, 2016 at 1:28 pm

Thanks all, got it working.

@Dan Potter: used your suggestion and was about to post back as I wanted to put the output into a variable for reporting...
@daniel Krebs: Your script was the final piece.

Cheers

September 20, 2016 at 1:33 pm

Great. I'm glad you've found my answer helpful.