$Disk query exports as SystemObject?

Hi guys, I have a starting script for system info, that needs to be exported to a csv. If I export the $Disk info only, this saves correctly, but as part of the script (see below) just returns as SYSTEM Object? I need to record capacity, used space and %free per disk, and export as part of a wider script:


$Disk = Get-WmiObject -Class Win32_LogicalDisk -Filter “DriveType=3” | Sort-Object -Property Name | Select-Object Name, `
@{“Label”=“DiskSize(GB)”;“Expression”={"{0:N2}" -f ($.Size/1GB) -as [float]}}, `
@{“Label”=“FreeSpace(GB)”;“Expression”={"{0:N2}" -f ($
.FreeSpace/1GB) -as [float]}}, `
@{“Label”="% Free";“Expression”={"{0:N}" -f ($.FreeSpace/$.Size*100) -as [float]}}

$H = $Env:Computername
$Path = “C:\Test”
$OS = (Get-WMIObject win32_operatingsystem)
$OSName = $OS.caption
$Serial = (Get-WMIObject win32_Bios).Serialnumber

$ipV4 = (Test-Connection -ComputerName ($H) -Count 1 | Select -ExpandProperty IPV4Address).IPAddressToString

#Memory Info:

$Mem = Get-WMIObject Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}
$PctFree = [math]::Round(($OS.FreePhysicalMemory/$OS.TotalVisibleMemorySize)*100,2)
$PCTFree = $PctFree = " %"
$Free = [math]::Round($OS.FreePhysicalMemory/1mb,2)
$Used = ($Mem - $Free)
$Mem = $Mem + " GB"
$Page = (Get-Counter “\$H\Memory\Pool Paged Bytes”).Countersamples | Select-Object -ExpandProperty cookedvalue
$Page = ("{0:N2}" -f ([math]::Round($Page/1mb)))
$Page = “Page File Size : " +$Page + " Mb”

#CPU Info:

$CPUInfo = ((get-counter -Counter “\Processor(_Total)% Processor Time” -SampleInterval 1 -MaxSamples 10 |
select -ExpandProperty countersamples | select -ExpandProperty cookedvalue | Measure-Object -Average).average)
$CPU = ("{0:N2}" -f ($CPUInfo))
$CPU = “CPU Used: " + $CPU + " %”

$Output = [pscustomobject]@{

ServerName = $H
OperatingSystem = $OSName
SerialNumber = $Serial
Memory = $Mem
Used = $Used
PercentFree = $PctFree
Paged = $Page
Disks = $Disk
$Output | Export-CSV -Path $Path$H.csv -NoTypeInformation


Is there a better way to do this, and so it actually shows the information? If I run the following separately, this creates a csv with the relevant information:



$DISK = “C:\Test\2-Disks.csv”
Get-WmiObject -Class Win32_LogicalDisk |
Where-Object {$.DriveType -ne 5} |
Sort-Object -Property Name |
Select-Object Name, VolumeName, VolumeSerialNumber, FileSystem, Description, `
@{“Label”=“DiskSize(GB)”;“Expression”={"{0:N}" -f ($
.Size/1GB) -as [float]}}, `
@{“Label”=“FreeSpace(GB)”;“Expression”={"{0:N}" -f ($.FreeSpace/1GB) -as [float]}}, `
@{“Label”="%Free";“Expression”={"{0:N}" -f ($
.FreeSpace/$_.Size*100) -as [float]}} | Export-CSV $DISK -noTypeInformation



I need to combine this with other information.


Many thanks



Line 19 needs to be changed to [pre] $PCTFree = “$PctFree %” [/pre]

Otherwise, when I run the top part, everything comes out okay. Which field is returning just a system object for you?


$Disk inside a custom object will have its type in a csv. Because there is no way that in a column we can have another object in tabular view.
Try below

$Output = [pscustomobject]@{

ServerName = $H
OperatingSystem = $OSName
SerialNumber = $Serial
Memory = $Mem
Used = $Used
PercentFree = $PctFree
Paged = $Page
DiskSize(GB) = $Disk."DiskSize(GB)"
"FreeSpace(GB)" = $Disk."FreeSpace(GB)"
"% Free" = $Disk."% Free"

Ah yeah, that’s probably it!

I’ve only got a single disk over here, so didn’t catch that.

There should be a ton of examples of reports like this on the interwebs. Here are the problems at first glance:

  • WMI - You should really be using Get-CimInstance over Get-WmiObject, Get-WmiObject uses DCOM which is basically deprecated
  • ComputerName - You're referencing a computer in one command, but none of the others. All of the commands should be referencing -ComputerName if you intend on being able to run this against remote systems.
  • Error Handling - There is no error handling. Minimally, you want to use Test-Connection to validate you can reach a computer. If you can, then attempt to connect with WMI.
  • Disks - You are returning an object. This object is basically nested under your $Output object, which is why it is showing as an Object.
  • CSV - For a report like this, because of items like Disks, a CSV is a bad choice. You should consider utilizing HTML reporting with ConvertTo-HTML. There is a free eBook on the left under Free Resources about reporting that will most likely even have information on the a hardware inventory.

thanks for all your help guys…will investigate Kvprasoon’s suggestions…

thanks guys - Kvprasoon’s help didn’t actually work, unfortunately (empty fields). Rob, understand the -computername usage - was just using this as a test sofar (on 1 pc only). The wmic is due to customer’s setup only. they want .csv then into excel as a report (ultimate goal).


$Output = [pscustomobject]@{

ServerName = $H
OperatingSystem = $OSName
SerialNumber = $Serial
Memory = $Mem
Used = $Used
PercentFree = $PctFree
Paged = $Page
'DiskSize(GB)' = "{0:N2}" -f ($Disk.Size/1GB) -as [float]
'FreeSpace(GB)' = "{0:N2}" -f ($Disk.FreeSpace/1GB) -as [float]
'% Free' = "{0:N}" -f ($Disk.FreeSpace/$_.Size*100) -as [float]

You will still have issues if you have multiple logical disks. So you could some Excel output.

Checkout ImportExcel module by Douge Finke, Its the best know module to create excel ouputs in PowerShell

Think of how you will need to format this. I don’t see a disk id or name in your disk results, so how would you know what partition you’re reporting on? Lets say we have

DiskId (e.g. C:)

You have disks 2 on the server, so your header row is going to be something like this to create unique header values:


In order to do that, we have to rip the object apart and rebuild it:

$output = @()
$output += [pscustomobject]@{
    ServerName = 'Server1'
    OperatingSystem = 'Windows Server 2016'
    SerialNumber = '312fef12'
    Memory = 16
    Disks = [pscustomobject]@{
                'DiskId' = 'C:' 
                'DiskSize(GB)' = '99'
                'FreeSpace(GB)' = '28'
                'PctFree' = '28'
                'DiskId' = 'D:' 
                'DiskSize(GB)' = '500'
                'FreeSpace(GB)' = '180'
                'PctFree' = '36'

$output += [pscustomobject]@{
    ServerName = 'Server2'
    OperatingSystem = 'Windows Server 2016'
    SerialNumber = '42rwrrg13g13'
    Memory = 32
    Disks = [pscustomobject]@{
                'DiskId' = 'C:' 
                'DiskSize(GB)' = '60'
                'FreeSpace(GB)' = '32'
                'PctFree' = '53'

$myNewOutput = foreach ($srv in $output) {
    #Get the flat properties and start a hash table
    $newObjProps = @{
        ServerName = $srv.ServerName
        OperatingSystem = $srv.OperatingSystem
        SerialNumber = $srv.SerialNumber
        Memory = $srv.Memory

    #Loop thru the disks and sort them on Id (e.g. C:, D:, etc.)
    for ($d = 0;$d -lt (@($srv.Disks | Sort-Object -Property DiskId).Count);$d++) {
        #Now we need to rip apart the object and make it flat.  We loop through
        #each property and build a column on property name and append the index and
        #set the property value
        foreach ($prop in $srv.Disks[$d].PSObject.Properties) {
            $newObjProps.Add(('{0}_{1}' -f $prop.Name, $d), $prop.Value)

    #Generate our new ripped apart object



DiskId_0        : C:
PctFree_1       : 36
DiskId_1        : D:
ServerName      : Server1
SerialNumber    : 312fef12
DiskSize(GB)_1  : 500
DiskSize(GB)_0  : 99
PctFree_0       : 28
Memory          : 16
FreeSpace(GB)_0 : 28
FreeSpace(GB)_1 : 180
OperatingSystem : Windows Server 2016

DiskId_0        : C:
ServerName      : Server2
SerialNumber    : 42rwrrg13g13
DiskSize(GB)_0  : 60
PctFree_0       : 53
Memory          : 32
FreeSpace(GB)_0 : 32
OperatingSystem : Windows Server 2016