Combine values from two different commands in one table

I have two functions in a powershell library that I use to monitor server disks. They both work but I want to merge them into one function so the output is in a single table. I’m sure a trained eye can easily see how to do this but I’m stuck. Any assistance is appreciated.

FUNCTION #1

function Get-DiskHealth {
   Get-PhysicalDisk -CimSession (Get-Content .\Servers.txt) -ErrorAction SilentlyContinue | `
       Where Model -NotLike "Virtual*" | `
       Get-StorageReliabilityCounter | `
       Sort PSComputername,DeviceID | `
       Format-Table -AutoSize `
           PSComputerName, `
           @{n="ID";e={($_.DeviceID)};align="right"}, `
           @{n="Temp";e={ConvertTo-Fahrenheit $_.Temperature}}, `
           @{n="Hrs";e={$_.PowerOnHours}}, `
           @{n="Years";e={"{0:N2}" -f($_.PowerOnHours/365/24)};align="right"}, `
           @{n="Cycles";e={$_.StartStopCycleCount}}, `
           @{n="Latency (R/W/Flush)";e={($_.ReadLatencyMax),($_.WriteLatencyMax),($_.FlushLatencyMax)}}, `
           @{n="Read Err (Tot/Fx/NFx)";e={($_.ReadErrorsTotal),($_.ReadErrorsCorrected),($_.ReadErrorsUncorrected)}}
}

produces output like this:

PSComputerName  ID Temp    Hrs Years Cycles Latency (R/W/Flush)  Read Err (Tot/Fx/NFx)
--------------  -- ----    --- ----- ------ -------------------  ---------------------
Server1          0 96.8  19155  2.19 45     {2637, 4486, 2673}   {0, 0, 0}
Server1          1 92.7   6988  0.80 52     {3637, 4786, 2373}   {0, 0, 0}

FUNCTION #2

function Get.AllPhysicalDisks {
Get-PhysicalDisk -CimSession (Get-Content .\Servers.txt) -ErrorAction SilentlyContinue -ErrorVariable e | `
    Where Model -NotLike "Virtual*" | `
    Where Model -NotLike "*USB*" | `
    Sort PSComputername,DeviceID | `
    Format-Table -AutoSize `
        @{n="Server";e={$_.PSComputerName};align="left"}, `
        @{n="ID";e={$_.DeviceID};align="right"}, `
        @{n="Manufctr";e={(($_.Manufacturer).TrimStart()).TrimEnd()};align="right"}, `
        @{n="Model";e={(($_.Model).TrimStart()).TrimEnd()};align="right"}, `
        @{n="SerialNumber";e={(($_.SerialNumber).TrimStart()).TrimEnd()};align="right"}, `
        @{n="Firmware";e={($_.FirmwareVersion).TrimStart()};align="right"}, `
        @{n="Size(GB)";e={"{0:N2}" -f($_.Size/1GB)};align="right"}, `
        @{n="Status(Hlth/Op)";e={($_.HealthStatus),($_.OperationalStatus)};align="center"}
}

produces output like this:

Server  ID Manufctr                 Model       SerialNumber Firmware Size(GB) Status(Hlth/Op)
------  -- --------                 -----       ------------ -------- -------- ---------------
Server1  0          KINGSTON SA400S37120G     500B73801FBCED SBFKB1D1   111.79  {Healthy, OK}
Server1  1          KINGSTON SA400S37120G     500B73801FBCED SBFKB1D1   111.79  {Healthy, OK}

I want to combine the functions so I get an output table like this:

Server   ID Size(GB)  Temp   Hrs Years Cycles Manufctr/Model        SerialNumber   Firmware Latency (R/W/Flush) Read Err (Tot/Fx/NFx) Status(Hlth/Op)
-------  -- -------   ----   --- ----- ------ --------------        ------------   -------- ------------------- --------------------- ---------------
Server1   0  111.79   96.8 19155  2.19 45     KINGSTON SA400S37120G 500B73801FBCED SBFKB1D1  {2637, 4486, 2673}  {0, 0, 0}             {Healthy, OK}
Server1   1  111.79   92.7  6988  0.80 52     KINGSTON SA400S37120G 500B73801FBCED SBFKB1D1  {3637, 4786, 2373}  {0, 0, 0}             {Healthy, OK}

What is the best way to accomplish this?

$dskHlth = @"
PSComputerName,ID,Temp
Server1,0,96.8
Server1,1,92.7
"@ | ConvertFrom-Csv

$physDsk = @"
Server,ID,Manufacturer
Server1,0,KINGSTON SA400S37120G
Server1,1,KINGSTON SA400S37120G
"@ | ConvertFrom-Csv

$results = foreach ($disk in $dskHlth) {
    $join = $physDsk | Where{$_.id -eq $disk.id -and $_.PSComputerName -eq $disk.Server}

    if ($join) {
        $disk | Select *,
                       @{Name='Manufacturer';Expression={$join.Manufacturer}}
    }
}

$results

psh,
Welcome to the forum.

I had a similar idea like Rob …

function Get-PhysicalDiskHealth {
    param (
        [string[]]
        $ComputerName = $env:COMPUTERNAME
    )
    $CimSession = New-CimSession -ComputerName $ComputerName
    $HealthList = 
        Get-PhysicalDisk -CimSession $CimSession -OutVariable DiksList | 
            Get-StorageReliabilityCounter -CimSession $CimSession
    
    foreach ($Disk in $DiksList) {
        $Health = $HealthList | Where-Object { $_.PSComputerName -eq $Disk.PSComputerName -and $_.DeviceID -eq $Disk.DeviceID }
        [PSCustomObject]@{
            ComputerName    = $Disk.PSComputerName
            ID              = $Disk.DeviceID
            FriendlyName    = $Disk.FriendlyName
            Temp            = (ConvertTo-Fahrenheit $Health.Temperaure)
            Manufctr        = $Health.Manufacturer
            Model           = $Disk.Model
            WriteLatencyMax = $Health.WriteLatencyMax
        }
    }
}

I just used some of the properties you used. But I hope you get the idea of how to combine two sets of results in one PSCustomObject.

I intentionally omitted the input from the text file with the server names and the formatting as this makes a function less versatile. You should provide the list of computer names as a parameter to the function and add a formatting with a pipe in case you need it. Of course you could pipe the output to anything else this way what’s not working if you had the formatting inside your function.

I’d change the output of the temperature as well to make it independend from helper functions like ConvertTo-Fahrenheit which may not always available.