Adding Collection of PSObjects to a PSObject?

by kittH at 2013-04-18 06:01:05

Hey Guys, working on a script to collect some VM info… assuming that $VM is the output of a Get-VM…

Foreach ($VM in $VMs)
{
Write-Verbose "Scanning VM $($VM.Guest.Hostname)"
$Server = New-Object -TypeName PSObject
$Server | Add-Member -MemberType NoteProperty -Name Name -value ($VM.Guest.HostName -replace "..*")
$Server | Add-Member -MemberType NoteProperty -Name Domain -Value ($VM.Guest.Hostname.Replace("$($Server.Name).", ''))
$Server | Add-Member –MemberType NoteProperty –Name OS -Value $VM.Guest.OSFullName
$Server | Add-Member –MemberType NoteProperty –Name CoresPerCPU -Value $VM.ExtensionData.Config.Hardware.NumCoresPerSocket
$Server | Add-Member –MemberType NoteProperty –Name CPUs -Value ($VM.ExtensionData.Config.Hardware.NumCPU / $Server.CoresPerCPU)
$Server | Add-Member –MemberType NoteProperty –Name MemoryGB -Value ([math]::round($VM.MemoryGB))
$Server | Add-Member –MemberType NoteProperty –Name Serial -Value ($VM.ExtensionData.Config.Uuid).Replace('-', '')
$Server | Add-Member -MemberType NoteProperty -Name Processor -Value $Processor
$Server | Add-Member -MemberType NoteProperty -Name HardwareVersion -Value $VM.Version.ToString().Replace('v', '')
Foreach ($DiskObject in $VM.ExtensionData.Guest.Disk)
{
$Disk = New-Object -TypeName PSObject
$Disk | Add-Member -MemberType NoteProperty -Name Server -Value $Server.Name
$Disk | Add-Member -MemberType NoteProperty -Name DriveLetter -Value $DiskObject.DiskPath
$Disk | Add-Member -MemberType NoteProperty -Name Capacity -Value ([math]::round(($DiskObject.Capacity / 1GB), 2))
$Disk | Add-Member -MemberType NoteProperty -Name FreeSpace -Value ([math]::round(($DiskObject.FreeSpace / 1GB), 2))
$Disk | Add-Member -MemberType NoteProperty -Name PercentFree -Value ([math]::Round(($Disk.Freespace / $Disk.Capacity) * 100))
$Disks += $Disk
}

I have a $Server with a bunch of information, and $disks with potentially one, potentially many disks.
How can I add the disks to the $server object so that for example $Server.Disks would return the $disks collection? Feels like I might be missing something simple but having trouble wrapping my head around it.
by happysysadm at 2013-04-18 06:23:26
Hi Kitth,

as far as I can see you are not declaring $disks as an array, so when you add += $disk I think you get an op_addition error.

To solve this just declare $disks as an array just before $Disks += $Disk:
[code2=powershell]$Disks = @()[/code2]
Once you have done that you can add $disks as a member of $server:
[code2=powershell]$server | Add-Member -MemberType NoteProperty -Name Disks -value $disks[/code2]
Now $server.disks should return the array you asked for.

HTH
Carlo
by poshoholic at 2013-04-18 06:34:15
I think that won’t quite solve the problem as explained because it would clear the array every time you pass through the foreach loop. Instead, I would make two changes:

1. On the line before the inner foreach loop, add the following command:
$server | Add-Member -MemberType NoteProperty -Name Disks -value @()
2. In place of $Disks += $Disk, use the following syntax:
$server.Disks += $Disk
by kittH at 2013-04-18 06:48:05
Yeah sorry, I snipped out of my script, $Disks = @() is declared earlier.

That being said, Kirks version seems cleaner for how I am handling it now.

Thanks to you both.
by happysysadm at 2013-04-18 06:50:39
I agree with you.
Carlo
by MasterOfTheHat at 2013-04-19 06:38:52
[quote="poshoholic"]I think that won’t quite solve the problem as explained because it would clear the array every time you pass through the foreach loop. Instead, I would make two changes:

1. On the line before the inner foreach loop, add the following command:
$server | Add-Member -MemberType NoteProperty -Name Disks -value @()
2. In place of $Disks += $Disk, use the following syntax:
$server.Disks += $Disk[/quote]
Your explanation definitely works, but I’m wondering why clearing the $disks array each time you enter the "top" foreach loop is a problem? The OP is creating a new $disks array for each $VM, so he would need a new array declared each time anyway, right? If the array was cleared/recreated before the inner foreach loop, the array was built during that loop, and then it was added to the PSObject after that loop, you would have the same outcome, right?

Again, I see nothing wrong with the solution you presented; I just want to make sure I’m not missing something.