PowerShell Hardware & Software Inventory Script

An essential guide for IT professionals to collect detailed hardware and software inventory from Windows computers.

In this Guide:

Introduction

Manually tracking the hardware and software on every computer in your organisation is a big job. This script is a PowerShell hardware inventory script that does the work for you. Designed for IT professionals, system administrators and MSP, this script collects all the computer specs and puts them into a clean easy to read CSV report.

Using this asset management script you can simplify asset tracking, license management and troubleshooting and save time and resources.

Background

Accurate IT inventory data is key to good management. Without a way to collect this data IT teams struggle with tasks like planning hardware upgrades, software license compliance or finding which machine has a specific component for troubleshooting. The challenge is collecting all the data points – from serial numbers and memory size to installed applications and CPU models – without manual intervention.

This Windows inventory automation solution solves this problem by using PowerShell to query Windows Management Instrumentation (WMI) and Common Information Model (CIM) classes and give you a comprehensive and up to date hardware report from every machine.

Script Code

Here is the complete PowerShell script. You can save this as a .ps1 file.

Get-HardwareInventory.ps1
Copy to clipboard
# SCRIPT_NAME: Get-HardwareInventory.ps1
# DESCRIPTION: Gathers detailed hardware and software information and outputs to a CSV file.
# PARAMETERS:
# -c: Consolidates all individual inventory CSVs in the output directory into a single, comprehensive report.

param(
    [switch]$c
)

# --- CONFIGURATION ---
$outputDir = "C:\InventoryReports"
$consolidationFile = "Consolidated_Inventory_Report.csv"

# --- CONSOLIDATION LOGIC ---
if ($c) {
    if (-not (Test-Path $outputDir)) {
        Write-Host "Output directory not found. Please run the script on client machines first." -ForegroundColor Red
        exit
    }
    
    $csvFiles = Get-ChildItem -Path $outputDir -Filter "*.csv" | Where-Object { $_.Name -ne $consolidationFile }
    if (-not $csvFiles) {
        Write-Host "No individual inventory CSV files found to consolidate." -ForegroundColor Yellow
        exit
    }
    
    Write-Host "Consolidating all inventory files..."
    $allData = @()
    foreach ($file in $csvFiles) {
        $allData += Import-Csv -Path $file.FullName
    }
    
    $allData | Export-Csv -Path (Join-Path $outputDir $consolidationFile) -NoTypeInformation -Force
    Write-Host "Consolidation complete. Report saved to $($consolidationFile)." -ForegroundColor Green
    exit
}

# --- INVENTORY COLLECTION LOGIC ---
# Create output directory if it does not exist
if (-not (Test-Path $outputDir)) {
    New-Item -ItemType Directory -Path $outputDir | Out-Null
}

try {
    # Gather System Information
    $osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
    $computerInfo = Get-CimInstance -ClassName Win32_ComputerSystem
    $biosInfo = Get-CimInstance -ClassName Win32_BIOS
    $networkInfo = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration | Where-Object { $_.IPAddress }
    $processorInfo = Get-CimInstance -ClassName Win32_Processor
    $ramInfo = (Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB
    $gpuInfo = Get-CimInstance -ClassName Win32_VideoController
    $storageInfo = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 }
    $monitors = Get-CimInstance -ClassName Win32_DesktopMonitor

    # Get Uptime
    $lastBootTime = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
    $uptime = (New-TimeSpan -Start $lastBootTime).ToString("g")

    # Get Installed Software
    $installedApps = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
                     Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Where-Object {$_.DisplayName -ne $null} | Sort-Object DisplayName

    # Create a custom object for the report
    $report = [PSCustomObject]@{
        "Date of Inventory" = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "Hostname" = $computerInfo.Name
        "IP Address" = ($networkInfo.IPAddress | Select-Object -First 1) -join ', '
        "MAC Address" = ($networkInfo.MACAddress | Select-Object -First 1) -join ', '
        "Username" = $computerInfo.PrimaryOwnerName
        "Computer Type" = $computerInfo.PCSystemTypeDescription
        "Manufacturer" = $computerInfo.Manufacturer
        "Model" = $computerInfo.Model
        "Serial Number" = $biosInfo.SerialNumber
        "BIOS Version" = $biosInfo.SMBIOSBIOSVersion
        "CPU" = $processorInfo.Name
        "RAM (GB)" = [math]::Round($ramInfo, 2)
        "Total Storage (GB)" = [math]::Round(((Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Measure-Object -Property Size -Sum).Sum / 1GB), 2)
        "Free Storage (GB)" = [math]::Round(((Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Measure-Object -Property FreeSpace -Sum).Sum / 1GB), 2)
        "GPU(s)" = ($gpuInfo.Name -join ', ')
        "OS Name" = $osInfo.Caption
        "OS Version" = $osInfo.Version
        "Uptime" = $uptime
        "Monitor(s)" = ($monitors.Name -join ', ')
        "Installed Applications" = ($installedApps.DisplayName -join ', ')
    }
    
    # Define the output file path
    $outputFile = Join-Path $outputDir "$($computerInfo.Name)_inventory.csv"
    
    # Export the report to CSV
    $report | Export-Csv -Path $outputFile -NoTypeInformation -Force
    
    Write-Host "Inventory complete. Report saved to $($outputFile)." -ForegroundColor Green

} catch {
    Write-Host "An error occurred during inventory collection: $($_.Exception.Message)" -ForegroundColor Red
}

Detailed Breakdown

FeatureDescription
Data CollectionUses a variety of WMI and CIM classes to gather detailed system and hardware information.
For example, Get-CimInstance -ClassName Win32_ComputerSystem retrieves system details,
while Get-CimInstance -ClassName Win32_Processor focuses on CPU data.
Refer to Microsoft Learn's WMI documentation for a full list.
Consolidation Parameter (-c)The -c switch consolidates multiple CSV reports into a single master file, bypassing data collection logic.
It searches the output directory, merges CSVs, and generates a unified report.
Output to CSVThe script creates a [PSCustomObject] with structured properties for each data point.
It is exported via Export-Csv with the -NoTypeInformation parameter
to ensure clean, analysis-ready CSV files.
Error HandlingImplements try...catch blocks to ensure script robustness.
If data collection fails (e.g., missing info on a machine), the script logs the error and continues without crashing.

Potential Use Cases

  • IT Asset Tracking: Use the consolidated report to create a definitive list of all hardware assets, including serial numbers, models, and locations. This is fundamental for IT asset tracking and lifecycle management.

  • License Management: The script captures a list of installed applications, which can be invaluable for auditing software licenses. You can quickly identify which machines are running specific licensed software to ensure compliance and avoid costly penalties.

  • Hardware Upgrade Planning: By collecting details on RAM, CPU, and storage, you can easily filter your consolidated report to identify which computers are outdated and need to be replaced or upgraded.

  • Troubleshooting: When a user reports an issue, having a quick reference to their hardware specifications can help you diagnose the problem faster. The ability to collect computer specs on demand is a major time-saver.

Final Thoughts

This Hardware/PC Inventory report script is more than just a tool, it's a foundation for a more proactive and efficient IT management strategy. By deploying this script as a login script via a Group Policy Object, for example, you can ensure that your inventory data is always up-to-date and ready for analysis. This simple automation can transform the way you manage your assets, moving from reactive to proactive maintenance.

Deploy this script across your Endpoints with Zecurit

Upload this script to Zecurit's Script Repository and execute it across hundreds of endpoints in minutes. Support for PowerShell, Bash, Python,and more with full audit trails and scheduling.

Frequently Asked Questions (FAQs)

  • What permissions do I need to run this script?

    The script requires local administrator rights to query WMI/CIM classes and to write files to the specified output directory. If you are deploying it as a login script, the local administrator context is typically used.

  • How do I deploy this as a login script?

    You can use Group Policy Management on a domain controller. Create a new GPO, go to User Configuration > Policies > Windows Settings > Scripts (Logon/Logoff), and add the .ps1 file. This will ensure the script runs every time a user logs in.

  • Is it safe to run this on a production environment?

    Yes. The script is a read-only tool that queries system information without making any changes to the system. The performance impact is minimal, as it is a lightweight process designed for data collection.

  • How can I collect inventory from remote computers?

    While this script is designed to run locally on each machine, you can adapt it to run remotely using the Invoke-Command cmdlet. When managing large-scale remote inventory, Zecurit, a centralized management tool, is typically more efficient