Introduction
A solid automation foundation begins with mastering inventory visibility. Whether you’re building reports, generating audits, or feeding automation workflows, PowerCLI provides deep access into your vSphere inventory with consistent object models.
In this article, we’ll cover:
- Discovering VMs, hosts, clusters, datastores, and networks
- Filtering objects with precision
- Exporting to CSV, HTML, and JSON
- Grouping and reporting by custom fields
- Common pitfalls and edge cases
My Personal Repository on GitHub
Listing Core Inventory Objects
Once connected via Connect-VIServer, use Get-* cmdlets to extract the environment’s current state.
# List all VMs
Get-VM
# List all hosts
Get-VMHost
# List all datastores
Get-Datastore
# List all networks and port groups
Get-VirtualPortGroup
For clusters and folders:
Get-Cluster
Get-Folder -Name "Production"
Filtering VMs with Specific Criteria
# Find powered off VMs
Get-VM | Where-Object {$_.PowerState -eq "PoweredOff"}
# Find VMs by name pattern
Get-VM | Where-Object {$_.Name -like "*SQL*"}
# VMs with more than 4 CPUs and over 16GB memory
Get-VM | Where-Object { $_.NumCPU -gt 4 -and $_.MemoryGB -gt 16 }
This enables rapid root-cause analysis or sizing validation.
Exporting VM Inventory Reports
Generate a standardized CSV report for audits or documentation.
$vmReport = Get-VM | Select-Object Name, PowerState, NumCPU, MemoryGB, VMHost, @{N="Datastore";E={($_ | Get-Datastore).Name}}
$vmReport | Export-Csv -Path "C:\Reports\VM_Inventory.csv" -NoTypeInformation
Alternate formats:
# HTML
$vmReport | ConvertTo-Html | Out-File "C:\Reports\VM_Inventory.html"
# JSON
$vmReport | ConvertTo-Json | Out-File "C:\Reports\VM_Inventory.json"
Grouping and Aggregation
Example: Show VM counts by host.
Get-VM | Group-Object -Property VMHost | Select Name, Count
Sample Output:
Name Count
---- -----
esxi01.lab.local 42
esxi02.lab.local 39
Use Measure-Object to check resource allocation:
Get-VM | Measure-Object -Property MemoryGB -Sum
Advanced Filtering: Tags, Guest OS, Custom Attributes
# VMs running Windows
Get-VM | Where-Object {$_.Guest.OSFullName -like "*Windows*"}
# VMs tagged with 'Production'
Get-TagAssignment | Where-Object {$_.Tag.Name -eq "Production"} | Select Entity
# With a specific annotation
Get-VM | Where-Object {$_.Notes -like "*database*"}
Host and Cluster Inventory Reports
Extract host-level configuration and export:
Get-VMHost | Select-Object Name, ConnectionState, Manufacturer, Model, ProcessorType, MemoryTotalGB, Version | Export-Csv -Path "C:\Reports\Host_Inventory.csv" -NoTypeInformation
Grouped by cluster:
Get-VMHost | Group-Object -Property Parent | Select Name, Count
Diagram: Inventory Object Relationships

Common Mistakes and Fixes
| Issue | Fix |
|---|---|
Get-VM returns nothing | Ensure connection to vCenter, not individual ESXi host |
| CSV missing datastore or host | Use calculated properties (@{N=;E=} blocks) |
| Output includes system VMs or templates | Filter with Where-Object { -not $_.ExtensionData.Config.Template } |
| Script fails on large environments | Use -PipelineVariable and streaming with Export-Csv -Append |
Sample Use Case: Datastore Utilization Summary
Get-Datastore | Select Name, CapacityGB, FreeSpaceGB, @{N="UsedPercent";E={[math]::Round((($_.CapacityGB - $_.FreeSpaceGB)/$_.CapacityGB)*100,2)}} | Export-Csv "C:\Reports\Datastore_Utilization.csv" -NoTypeInformation
What’s Next
In the next article, we’ll explore bulk VM operations, including:
- Powering on/off large groups of VMs
- Automating snapshots and removals
- Batch tagging, notes, and updates
- Graceful shutdown/startup sequences