Deal with system object for PSCustom Object RRS feed

  • Question

  • I'm trying to see how I would dynamically deal with a system object that could have various sizes.

    I'm writing a script to inventory a number of servers and one of the items of interest is how many drives the server has.

    Now the issue is that some server may have 1 or 2 drives, while other may have up to 8 drives.

    The question is how to add (dynamically) the number of drives (plus info) into the results pscustomobject?

    The code I currently have is below:

    Set-Location $PSScriptRoot
    $servers = Get-Content .\servers.txt
    $Results = foreach($server in $servers){
    	If (Test-Connection $server -Count 1 -ErrorAction SilentlyContinue)
            $WMIName = $null
            $WindowsVer = $null
            $IPAddress = $null
            $RAM = $null
            $Drives = $null
            $WMIName = (Get-WmiObject Win32_ComputerSystem -ComputerName $server -ErrorAction SilentlyContinue).name
            If($WMIName -eq $null){
                Write-Host "WMI Connection Failed" -ForegroundColor Red
                $WindowsVer = (Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction SilentlyContinue).Caption
                $IPAddress = Test-Connection $server -Count 1 -ErrorAction SilentlyContinue | select IPV4Address
                $RAM = [math]::Round((Get-WmiObject -Class Win32_ComputerSystem -ComputerName $server).TotalPhysicalMemory/1GB)
                $Drives = Get-WmiObject -Class Win32_logicaldisk -ComputerName $server -Filter "DriveType = '3'" | Select-Object -Property DeviceID, VolumeName, @{L='FreeSpaceGB';E={"{0:N2}" -f ($_.FreeSpace /1GB)}}, @{L="Capacity";E={"{0:N2}" -f ($_.Size/1GB)}}
            "Machine" = $server;
            "OS"   = $WindowsVer;
            "IPAddress" = $IPAddress.IPV4Address;
            "RAM" = "$RAM Gb";
            "Drives" = $Drives;
    $Results | Export-Csv -NoTypeInformation .\Results.csv 

    Wednesday, April 22, 2020 4:48 PM

All replies

  • You're already doing that. Your "Drives" property will be an array of objects if there are more than one drive (e.g. Object[] if you looked at its type). In that array of objects there will be one element of type PSCustomObject for each drive.

    --- Rich Matheisen MCSE&I, Exchange Ex-MVP (16 years)

    Wednesday, April 22, 2020 6:37 PM
  • Yeah there is a Object[] element displayed in the output, but how would that be exported with the other elements for the server? (Name, RAM etc.)

    So say I have a server with 5 drives, and each of those 5 drives have 4 properties. How would those 20 properties be exported for the 1 server? And then continue onto the next server which may only have 2 drives?

    With the current script I have those drives are only being displayed as System.Object[]

    I could cycle through each drive object and create variables for each drive property, and then add those to the custom object but I'd have to write code to compensate for the different numbers of drives each server has.

    I was just wondering if there is a better, more efficient way of doing it?

    Wednesday, April 22, 2020 7:06 PM
  • As you've discovered, you can't export an array to a CSV. That's not because doing so is impossible, it's because a CSV has no way of representing the structure.

    So, the question now becomes how you want to see the contents of the array in the CSV. Do you want them all in the same cell? Do you want them in separate rows? What are you doing with the CSV? Do you want to do any processing with it? Or is it just for human consumption?

    If you want to see them all the same row, along with the other information you could wind up with a pretty wide spreadsheet.

    Using JSON or XML (both of which will unwind arrays and hashes) might be an alternative.

    --- Rich Matheisen MCSE&I, Exchange Ex-MVP (16 years)

    Wednesday, April 22, 2020 9:31 PM