Disclaimer
This is my personal blog. The opinions and views I express are my own. The information I provide is on an as-is basis. I make no representations as to accuracy, completeness, currentness, suitability, or validity of any information on this blog and will not be liable for any errors, omissions, or delays in this information or any losses, injuries or damages arising from its use.

Remote Computer Inventory with PowerShell

This script uses WMI CMDlets for the most part, to gather some client hardware and software information remotely over the network. Click the link below to see the contents of the CSV file. I use it to collect the following information:

  • Computer Name
  • Manufacturer
  • Model
  • Processor Type
  • System Type
  • Operating system
  • Operating system Version
  • Operating system Build Version
  • Serial Number
  • IP Address MAC Address
  • Last User logged in
  • Last User login time
  • C: free space in GBs
  • Total RAM in GBs
  • The date and time of the last reboot

Computer_inventory_spreadsh

The video below goes into a little more detail as far as the mechanics. In subsequent videos I plan to turn this into a function and possibly a workflow in order to make it a little more efficient.

#  *** THIS SCRIPT IS PROVIDED WITHOUT WARRANTY, USE AT YOUR OWN RISK ***
<#

.DESCRIPTION
	Use WMI to gather hardware and software information remotely from domain clients.
    The script pings a list of computernames and runs the inventory on livePCs.txt.
    Once all the hardware/software information is collected, all the data is exported
    to a CSV file. 

.NOTES
	File Name: Get-Inventory.ps1
	Author: David Hall
	Contact Info: 
		Website: www.signalwarrant.com
		Twitter: @signalwarrant
		Facebook: facebook.com/signalwarrant/
		Google +: plus.google.com/113307879414407675617
		YouTube Subscribe link: https://www.youtube.com/c/SignalWarrant1?sub_confirmation=1
	Requires: PowerShell Remoting Enabled (Enable-PSRemoting) 
	Tested: PowerShell V5, Windows 10, Windows Server 2012 R2

.PARAMETER 
    No parameters, just change the execution policy and run the script
		 
.EXAMPLE
     
#>

$testcomputers = Get-Content -Path 'C:\scripts\computers.txt'
$exportLocation = 'C:\scripts\pcInventory.csv'

# Test connection to each computer before getting the inventory info
foreach ($computer in $testcomputers) {
  if (Test-Connection -ComputerName $computer -Quiet -count 2){
    Add-Content -value $computer -path c:\scripts\livePCs.txt
  }else{
    Add-Content -value $computer -path c:\scripts\deadPCs.txt
  }
}


# Now that we know which PCs are live on the network
# proceed with the inventory

$computers = Get-Content -Path 'C:\scripts\livePCs.txt'

foreach ($computer in $computers) {
    $Bios = Get-WmiObject win32_bios -Computername $Computer
    $Hardware = Get-WmiObject Win32_computerSystem -Computername $Computer
    $Sysbuild = Get-WmiObject Win32_WmiSetting -Computername $Computer
    $OS = Get-WmiObject Win32_OperatingSystem -Computername $Computer
    $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer | Where-Object {$_.IPEnabled}
    $driveSpace = Get-WmiObject win32_volume -computername $Computer -Filter 'drivetype = 3' | 
    Select-Object PScomputerName, driveletter, label, @{LABEL='GBfreespace';EXPRESSION={'{0:N2}' -f($_.freespace/1GB)} } |
    Where-Object { $_.driveletter -match 'C:' }
    $cpu = Get-WmiObject Win32_Processor  -computername $computer
    $username = Get-ChildItem "\\$computer\c$\Users" | Sort-Object LastWriteTime -Descending | Select-Object Name, LastWriteTime -first 1
    $totalMemory = [math]::round($Hardware.TotalPhysicalMemory/1024/1024/1024, 2)
    $lastBoot = $OS.ConvertToDateTime($OS.LastBootUpTime) 

    $IPAddress  = $Networks.IpAddress[0]
    $MACAddress  = $Networks.MACAddress
    $systemBios = $Bios.serialnumber

    $OutputObj  = New-Object -Type PSObject
    $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.ToUpper()
    $OutputObj | Add-Member -MemberType NoteProperty -Name Manufacturer -Value $Hardware.Manufacturer
    $OutputObj | Add-Member -MemberType NoteProperty -Name Model -Value $Hardware.Model
    $OutputObj | Add-Member -MemberType NoteProperty -Name Processor_Type -Value $cpu.Name
    $OutputObj | Add-Member -MemberType NoteProperty -Name System_Type -Value $Hardware.SystemType
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System -Value $OS.Caption
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System_Version -Value $OS.version
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System_BuildVersion -Value $SysBuild.BuildVersion
    $OutputObj | Add-Member -MemberType NoteProperty -Name Serial_Number -Value $systemBios
    $OutputObj | Add-Member -MemberType NoteProperty -Name IP_Address -Value $IPAddress
    $OutputObj | Add-Member -MemberType NoteProperty -Name MAC_Address -Value $MACAddress
    $OutputObj | Add-Member -MemberType NoteProperty -Name Last_User -Value $username.Name
    $OutputObj | Add-Member -MemberType NoteProperty -Name User_Last_Login -Value $username.LastWriteTime
    $OutputObj | Add-Member -MemberType NoteProperty -Name C:_FreeSpace_GB -Value $driveSpace.GBfreespace
    $OutputObj | Add-Member -MemberType NoteProperty -Name Total_Memory_GB -Value $totalMemory
    $OutputObj | Add-Member -MemberType NoteProperty -Name Last_ReBoot -Value $lastboot
    $OutputObj | Export-Csv $exportLocation -Append -NoTypeInformation
  }

 

UPDATE: Below are the new video and the code for the functionalized version of the script above.

#  *** THIS SCRIPT IS PROVIDED WITHOUT WARRANTY, USE AT YOUR OWN RISK ***
<#

.DESCRIPTION
	Use WMI to gather hardware and software information remotely from domain clients.
    The script pings a list of computernames and runs the inventory on livePCs.txt.
    Once all the hardware/software information is collected, all the data is exported
    to a CSV file. 

.NOTES
	File Name: Get-Inventory.ps1
	Author: David Hall
	Contact Info: 
		Website: www.signalwarrant.com
		Twitter: @signalwarrant
		Facebook: facebook.com/signalwarrant/
		Google +: plus.google.com/113307879414407675617
		YouTube Subscribe link: https://www.youtube.com/c/SignalWarrant1?sub_confirmation=1
	Requires: PowerShell Remoting Enabled (Enable-PSRemoting) 
	Tested: PowerShell V5, Windows 10, Windows Server 2012 R2

.PARAMETER 
    ComputerName(s), see the examples below.
		 
.EXAMPLE
     .\Get-Inventory.ps1 -ComputerName CL1
     .\Get-Inventory.ps1 -ComputerName CL1, CL2
     .\Get-Inventory.ps1 -ComputerName (Get-Content -Path "C:\computers.txt")

.REFERENCES
    https://technet.microsoft.com/en-us/library/hh847806.aspx
     
#>

Function Get-Inventory {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [string[]]$Computers
        )


$exportLocation = "$env:HOMEDRIVE\scripts\"

# Test connection to each computer before getting the inventory info
foreach ($computer in $Computers) {
  if (Test-Connection -ComputerName $computer -Quiet -count 2){
    Add-Content -value $computer -path "$exportLocation\livePCs.txt"
  }else{
    Add-Content -value $computer -path "$exportLocation\deadPCs.txt"
  }
}


# Now that we know which PCs are live on the network
# proceed with the inventory

$computers = Get-Content -Path "$exportLocation\livePCs.txt"

foreach ($computer in $computers) {
    $Bios = Get-WmiObject -Class win32_bios -ComputerName $Computer
    $Hardware = Get-WmiObject -Class Win32_computerSystem -ComputerName $Computer
    $Sysbuild = Get-WmiObject -Class Win32_WmiSetting -ComputerName $Computer
    $OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer
    $Networks = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $Computer | Where-Object {$_.IPEnabled}
    $driveSpace = Get-WmiObject -Class win32_volume -ComputerName $Computer -Filter 'drivetype = 3' | 
    Select-Object -Property PScomputerName, driveletter, label, @{LABEL='GBfreespace';EXPRESSION={'{0:N2}' -f($_.freespace/1GB)} } |
    Where-Object { $_.driveletter -match 'C:' }
    $cpu = Get-WmiObject -Class Win32_Processor  -ComputerName $computer
    $username = Get-ChildItem "\\$computer\c$\Users" | Sort-Object -Property LastWriteTime -Descending | Select-Object -Property Name, LastWriteTime -First 1
    $totalMemory = [math]::round($Hardware.TotalPhysicalMemory/1024/1024/1024, 2)
    $lastBoot = $OS.ConvertToDateTime($OS.LastBootUpTime) 

    $IPAddress  = $Networks.IpAddress[0]
    $MACAddress  = $Networks.MACAddress
    $systemBios = $Bios.serialnumber

    $OutputObj  = New-Object -TypeName PSObject
    $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.ToUpper()
    $OutputObj | Add-Member -MemberType NoteProperty -Name Manufacturer -Value $Hardware.Manufacturer
    $OutputObj | Add-Member -MemberType NoteProperty -Name Model -Value $Hardware.Model
    $OutputObj | Add-Member -MemberType NoteProperty -Name Processor_Type -Value $cpu.Name
    $OutputObj | Add-Member -MemberType NoteProperty -Name System_Type -Value $Hardware.SystemType
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System -Value $OS.Caption
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System_Version -Value $OS.version
    $OutputObj | Add-Member -MemberType NoteProperty -Name Operating_System_BuildVersion -Value $SysBuild.BuildVersion
    $OutputObj | Add-Member -MemberType NoteProperty -Name Serial_Number -Value $systemBios
    $OutputObj | Add-Member -MemberType NoteProperty -Name IP_Address -Value $IPAddress
    $OutputObj | Add-Member -MemberType NoteProperty -Name MAC_Address -Value $MACAddress
    $OutputObj | Add-Member -MemberType NoteProperty -Name Last_User -Value $username.Name
    $OutputObj | Add-Member -MemberType NoteProperty -Name User_Last_Login -Value $username.LastWriteTime
    $OutputObj | Add-Member -MemberType NoteProperty -Name C:_FreeSpace_GB -Value $driveSpace.GBfreespace
    $OutputObj | Add-Member -MemberType NoteProperty -Name Total_Memory_GB -Value $totalMemory
    $OutputObj | Add-Member -MemberType NoteProperty -Name Last_ReBoot -Value $lastboot
    $OutputObj | Export-Csv -Path "$exportLocation\pcsinventory.csv" -Append -NoTypeInformation
  }
}  

 

6 Comments

  1. Michael Reynolds | | Reply

    How do i run this against a certain OU and not all of active directory?

  2. Richard | | Reply

    I figure out how by using Fabrice’s notes and the PS GET-HELP GET-ADComputer in PS.

    It resulted in this:

    $OU = Get-ADComputer -Filter {name -Like $computer} -Properties CanonicalName | Select CanonicalName

    $OutputObj | Add-Member -MemberType NoteProperty -Name OU -Value $OU.CanonicalName

    Works for my purpose!

  3. Richard | | Reply

    This works great for me. Much appreciated!

    Is there a way to add the ability to get what OU each system resides?

  4. Fabrice NOURRY | | Reply

    works fine for me ! thank you !

    #add description from active directory for my need

    $Description = Get-ADComputer -Filter {name -Like $computer} -Properties Description | Select Description

    $OutputObj | Add-Member -MemberType NoteProperty -Name Description -Value $Description.Description

    #and OS real install date (not upgrade date)

    $InstallDate = $wmi = Get-Item \\$computer\C$\Windows\CSC

    $OutputObj | Add-Member -MemberType NoteProperty -Name Install_Date -Value $InstallDate.LastWriteTime

    #and office version

    $OfficeVersionName = Get-WmiObject win32_product -ComputerName $Computer | where{$_.Name -like “*Office*”} | select Name | Get-Unique

    $OfficeVersion = Get-WmiObject win32_product -ComputerName $Computer | where{$_.Name -like “*Office*”} | select Version | Get-Unique

    $OutputObj | Add-Member -MemberType NoteProperty -Name Office_Name -Value $OfficeVersionName.Name
    $OutputObj | Add-Member -MemberType NoteProperty -Name Office_Version -Value $OfficeVersion.Version

  5. Prashant Gajjar | | Reply

    Hi David,
    this is looking great, but not working for me!! i have tried in two separate PC,.. no Luck 🙁 it is not giving any results.

  6. SL Manning | | Reply

    Hey David – know this is an older post, but I had a question. I have been running this script successfully for a while now; but we just started replacing some hardware. The new hardware has been on the network for about a week and the script is still reporting the old hardware specs (make, model, os, etc); is there a way to fix this?

Leave a Reply to Fabrice NOURRY Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.