Using hashtable to list snapshots by servername


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:

$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?


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


server = $vmhost
name = $name
snapshot = $snapshot
etc = ‘…’


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

$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


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

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.


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