Friday, December 12, 2014

Collecting computer/server inventory

A while back I wrote this handy little function for collecting inventory from the computers in my household. Somehow I never got around to posting it on my blog, for which I apologize ;-)

The function uses WMI to collect the following information from computers running windows:

Hostname and description
Serial number
Operations system
Uptime
Hardware: Mainboard, BIOS version, CPU, ram size and speed, local disks, GPU, NIC names and speed.

PowerShell function:


Function Get-Inventory {
    Param (
        [array]$computerName = '.'
    )
    $currentDate = (Get-Date).ToShortDateString()
    Foreach ($c in $computerName) {
        Try {
            $computerSystem = Get-WmiObject -ClassName Win32_ComputerSystem -Computername $c -Property Name, Domain -ErrorAction Stop
            $fqdn = "$($computerSystem.Name).$($computerSystem.Domain)"
            $mainboard = Get-WmiObject -ClassName Win32_Baseboard -Computername $c
            $bios = Get-WmiObject -ClassName Win32_BIOS -Computername $c
            $cpu = Get-WmiObject -ClassName Win32_Processor -Computername $c
            $ram = Get-WmiObject -ClassName Win32_PhysicalMemory -Computername $c -Property Capacity, Speed
            $ramSize = $ram | Measure-Object Capacity -sum | Select-Object -ExpandProperty sum
            $ramSize = "$([math]::round($ramSize / 1gb +0.5, 0)) GB"
            $ramSpeedMin = $ram | Measure-Object Speed -min | Select-Object -ExpandProperty minimum
            $ramSpeedMax = $ram | Measure-Object Speed -max | Select-Object -ExpandProperty maximum
            If ($ramSpeedMin -eq $ramSpeedMax) {
                $ramSpeed = "($ramSpeedMin MHz)"
            } Else {
                $ramSpeed = "($ramSpeedMin - $ramSpeedMax MHz)"
            }
            $ramInfo = "$ramSize $ramSpeed"
            $gpu = Get-WmiObject -ClassName Win32_VideoController -Computername $c
            $disks = Get-WmiObject -ClassName Win32_DiskDrive -computername $c
            $diskArray = foreach ($disk in $disks) {
                $size = [math]::round($disk.size / 1000000000,0)
                $name = $disk.caption
                "$name ($size GB)"
            }
            $nics = Get-WmiObject -ClassName Win32_NetworkAdapter -ComputerName $c -Filter 'Manufacturer != "Microsoft" or Netenabled = "true"' -Property Description, Speed
            $nicArray = Foreach ($nic in $nics) {
                If ($nic.Speed -ge 1000000000) {
                    $nicSpeed = "$($nic.Speed / 1000000000) Gb/s"
                } Elseif ($nic.Speed -gt 0) {
                    $nicSpeed = "$($nic.Speed / 1000000) Mb/s"
                } Else {
                    $nicSpeed = "Speed Unknown"
                }
                "$($nic.Description) ($nicSpeed)"
            }
            $os = Get-WmiObject Win32_operatingsystem -Computername $c
            $uptime = (Get-Date) - [Management.ManagementDateTimeConverter]::ToDateTime($os.LastBootUpTime)
            $uptimeString = "$($uptime.days) days, $($uptime.hours):$($uptime.minutes):$($uptime.seconds)"
            ## Create Output
            $obj = New-Object Object
            $obj | Add-Member Noteproperty Computername -value $fqdn
            $obj | Add-Member Noteproperty Description -value $os.description
            $obj | Add-Member Noteproperty CollectDate -value $currentDate
            $obj | Add-Member Noteproperty SerialNumber -value $bios.SerialNumber
            $obj | Add-Member Noteproperty Motherboard -value "$($mainboard.manufacturer) ($($mainboard.product))"
            $obj | Add-Member Noteproperty BIOSversion -value $bios.SMBIOSBIOSVersion
            $obj | Add-Member Noteproperty CPU -value $($cpu.name -replace ' {2,}','')
            $obj | Add-Member Noteproperty Memory -value $ramInfo
            $obj | Add-Member Noteproperty GPU -value $gpu.caption
            $obj | Add-Member Noteproperty HDD -value ($diskArray -join ', ')
            $obj | Add-Member Noteproperty NIC -value ($nicArray -join ', ')
            $obj | Add-Member Noteproperty OS -value "$($os.caption)$($os.csdversion) ($($os.osarchitecture))"
            $obj | Add-Member Noteproperty Uptime -value $uptimeString
            $obj
        } Catch {
            Write-Host "Connection to $c failed" -Foreground red
        }
    }
}

Examples of how to use the function against a single computer:

Get-Inventory myComputer

Several computers:

Get-Inventory myComputer1, myComputer2, myServerA

Getting the output in gridview:

Get-Inventory myComputer1, myComputer2, myServerA | Out-GridView

Saving the output to a .csv file for easy opening in excel:

Get-Inventory myComputer1, myComputer2, myServerA | ConvertTo-Csv -Delimiter ';' -NoTypeInformation | Out-File -FilePath inventory.csv -Encoding utf8 -Append