Issues with multiple pscustom objects and multiple for each loops

Good afternoon experts
Attempting to get the following script to work with multiple computers. If I set $serverlist to one computer the script works but when i set to $serverlist to multiple computers the script fails and not sure how to get it work. Don’t know how to combine the two for each loops together, had enough of a headache just getting the script to work with one computer.
Any suggestions as to how I can get this work for multiple computers?

thank you for any and all input

Norm

$ServerList = Get-ADComputer -Filter "OperatingSystem -like '*2012*'" -properties * | select-object -ExpandProperty Name
#$ServerList = $env:COMPUTERNAME

foreach ($ComputerName in $ServerList) {
$Session = New-CimSession -ComputerName $ComputerName
$System = Get-CimInstance -CimSession $Session -ClassName CIM_ComputerSystem
$OS = Get-CimInstance -CimSession $Session -ClassName CIM_OperatingSystem
$memalloc = [math]::round($System.TotalPhysicalMemory/1GB, 0)


[PSCustomObject]@{
ComputerName = $System.Name
RAM = $memalloc
Manufacturer = $System.Manufacturer
OS = $OS.Caption
OSVersion = $OS.Version
LastBootUpTime = $OS.LastBootUpTime

}

}

$Disks = get-wmiobject -class "Win32_LogicalDisk" -namespace "root\CIMV2" -ComputerName $ComputerName
foreach ($Disk in $Disks) {

if ($Disk.size -gt 0)
{

$size = [math]::round($disk.Size/1GB, 0)
$free = [math]::round($disk.FreeSpace/1GB, 0)
[PSCustomObject]@{
Drive = $disk.Name
"Total Disk Size" = $size
"Free Disk Size" = "{0:N0} ({1:P0})" -f $free, ($free/$size)
}
}
}

Your disk loop is outside the main computerlist loop.

This is one way of doing it:

$ServerList = Get-ADComputer -Filter "OperatingSystem -like '*2012*'" -properties * | select-object -ExpandProperty Name
#$ServerList = $env:COMPUTERNAME

foreach ($ComputerName in $ServerList) {
    $Session = New-CimSession -ComputerName $ComputerName
    $System = Get-CimInstance -CimSession $Session -ClassName CIM_ComputerSystem
    $OS = Get-CimInstance -CimSession $Session -ClassName CIM_OperatingSystem
    $memalloc = [math]::round($System.TotalPhysicalMemory/1GB, 0)

    $Disks = get-wmiobject -class "Win32_LogicalDisk" -namespace "root\CIMV2" -ComputerName $ComputerName
    $DiskObjects = foreach ($Disk in $Disks) {
        if ($Disk.size -gt 0) {
            $size = [math]::round($disk.Size/1GB, 0)
            $free = [math]::round($disk.FreeSpace/1GB, 0)
            [PSCustomObject]@{
                Drive = $disk.Name
                "Total Disk Size" = $size
                "Free Disk Size" = "{0:N0} ({1:P0})" -f $free, ($free/$size)
            }
        }
    }

    [PSCustomObject]@{
        ComputerName = $System.Name
        RAM = $memalloc
        Manufacturer = $System.Manufacturer
        OS = $OS.Caption
        OSVersion = $OS.Version
        LastBootUpTime = $OS.LastBootUpTime
        DiskInformation = $DiskObjects
    }
}

This uses a DiskInformation object under the main computer object

Hello Sam,
Thank you for your input, looks like we still have a issue with the output

ComputerName    : FWAPP171
RAM             : 12
Manufacturer    : VMware, Inc.
OS              : Microsoft Windows Server 2012 R2 Datacenter
OSVersion       : 6.3.9600
LastBootUpTime  : 3/21/2019 3:12:31 AM
DiskInformation : {@{Drive=C:; Total Disk Size=80; Free Disk Size=43 (54 %)}, @{Drive=D:; Total Disk Size=350; Free Disk Size=269 (77 %)}, @{Drive=E:; Total Disk Size=1000; Free Disk Size=717 (72 %)}, @{Drive=P:; Total Disk 
                  Size=8; Free Disk Size=4 (50 %)}}

Have not come across this type of issue before.

Again thanks for your input

Norm

Hello Sam;
Looks like I need to expand the contents of $DiskObjects. Did the following change and was able to get the drive id’s to display:
“$($DiskObjects.drive)”

Don’t know how to expand the contents of $Diskobjects to display Total Disk Size and Free Disk Size.

Thanks again for your input

Norm

Good afternoon experts
Would greatly appreciate some help with this script. Sam’s response was very helpful but have not been able to figure out how to fix the hash table output for $Diskobjects. Been working off and on for a couple of days trying to alter the pscustom object to deal with the hash table output but have failed to fix the problem. If someone could assist would greatly appreciate it!!!

$ServerList = Get-ADComputer -Filter "OperatingSystem -like '*2012*'" -properties * | select-object -ExpandProperty Name
#$ServerList = $env:COMPUTERNAME

foreach ($ComputerName in $ServerList) {
    $Session = New-CimSession -ComputerName $ComputerName
    $System = Get-CimInstance -CimSession $Session -ClassName CIM_ComputerSystem
    $OS = Get-CimInstance -CimSession $Session -ClassName CIM_OperatingSystem
    $memalloc = [math]::round($System.TotalPhysicalMemory/1GB, 0)

    $Disks = get-wmiobject -class "Win32_LogicalDisk" -namespace "root\CIMV2" -ComputerName $ComputerName
    $DiskObjects = foreach ($Disk in $Disks) {
        if ($Disk.size -gt 0) {
            $size = [math]::round($disk.Size/1GB, 0)
            $free = [math]::round($disk.FreeSpace/1GB, 0)
            [PSCustomObject][ordered]@{
                 Drive = $disk.Name
                "Total Disk Size" = $size
                "Free Disk Size" = "{0:N0} ({1:P0})" -f $free, ($free/$size)
            } 
        }
    }

    [PSCustomObject][ordered]@{
        ComputerName = $System.Name
        RAM = $memalloc
        Manufacturer = $System.Manufacturer
        OS = $OS.Caption
        OSVersion = $OS.Version
        LastBootUpTime = $OS.LastBootUpTime
        DiskInformation = $DiskObjects
    } 
} 

Thank you for help!!

Norm

Hello experts
Need some help with the output from this script, note the following output:

DiskInformation : {@{Drive=C:; Total Disk Size=80; Free Disk Size=43 (54 %)}, @{Drive=D:; Total Disk Size=350; Free Disk Size=269 (77 %)}, @{Drive=E:; Total Disk Size=1000; Free Disk Size=717 (72 %)}, @{Drive=P:; Total Disk Size=8; Free Disk Size=4 (50 %)}}

The output makes more sense found out pscustomobjects are effectively a superset of hashtables. Need some help converting $DiskObjects from a hashtable to for lack of better words to a normal output.

Hope this makes sense, appreciate any and all instance.

There are different ways to output the contents of a hashtable. Also, because the default output format for $DiskObjects is a table, and the hashtable is a list, you’re essentially trying to combine two different output formats as one output and this can make things messy.

The correct approach depends on what your goal is: is this just for console output, reporting, email notifications, etc?

Based on your code, the quick and dirty way would be to move DiskInformation outside the hashtable and pipe $DiskObjects to Out-String:

[PSCustomObject][ordered]@{
    ComputerName = $System.Name
    RAM = $memalloc
    Manufacturer = $System.Manufacturer
    OS = $OS.Caption
    OSVersion = $OS.Version
    LastBootUpTime = $OS.LastBootUpTime
}

Write-Output "Disk Information"

$DiskObjects | Out-String

or even better:

$DiskObjects.GetEnumerator()

The above would output disks in a table after the computer info output.

Output as a list:

$DiskObjects | Format-List

Keep in mind that you can’t append the individual objects from $DiskObjects to the hashtable because the hashtable keys have to be unique.

My personal preference is to throw everything into psobjects, wrap in a function, and make calls to that function and format output as necessary (for reporting, etc).

Edit: Sorry for multiple submits - formatting issues.

Hello Aaron,
For now simply looking for console output, played around with your suggestions made the following change

[PSCustomObject][ordered]@{
        ComputerName = $System.Name
        RAM = $memalloc
        Manufacturer = $System.Manufacturer
        OS = $OS.Caption
        OSVersion = $OS.Version
        LastBootUpTime = $OS.LastBootUpTime
        DiskInformation = $DiskObjects | Out-String 

and the change produced this:

ComputerName    : XXXXX01
RAM             : 16
Manufacturer    : Dell Inc.
OS              : Microsoft Windows Server 2012 R2 Standard
OSVersion       : 6.3.9600
LastBootUpTime  : 3/20/2019 10:16:49 PM
DiskInformation : 
                  Drive Total Disk Size Free Disk Size
                  ----- --------------- --------------
                  C:                100 73 (73 %)     
                  D:                200 200 (100 %)   
                  E:                398 396 (99 %)    
                  F:               1000 805 (81 %)    
                  G:                863 863 (100 %)

Ideally would have liked the output to be formatted as follows:

Computername   : XXXXX077
RAMGB          : 16
Manufacturer   : VMware, Inc.
OS             : Microsoft Windows Server 2012 R2 Datacenter
OSVersion      : 6.3.9600
LastBootUpTime : 3/28/2019 3:15:41 AM
Drive          : P
FileSystem     : NTFS
SizeGB         : 20
FreeGB         : 11.96
PctFree        : 59.8

Not sure my format desire is possible, never hurts to ask.

Thank you for responding been waiting for a response for days now.

Norm

Norm,

The ideal output you mentioned would only work if you had to report only one disk (and you would have to specify which one), but in reality that wouldn’t happen. When output contains more than one object (more than one disk), PowerShell wraps them all into a collection, a hashtable in this case. At this point, you’d have to pull everything back out by using .GetEnumerator() or some other means, depending on what you’re doing.

Glad to offer a workaround!

Aaron,
I’m content with the output/workaround.

Thanks again

Norm