Untitled
- <#
- .SYNOPSIS
- Inventory Hyper-V VMs: state, IPs, MACs, VLAN, disk provisioned/used, checkpoints. Exports to CSV.
- .EXAMPLE
- .\Get-HyperVInventory.ps1
- .\Get-HyperVInventory.ps1 -ComputerName HV01 -OutputDir D:\reports
- #>
- [CmdletBinding()]
- param(
- [string]$ComputerName = $env:COMPUTERNAME,
- [string]$OutputDir = 'C:\temp'
- )
- #Requires -Modules Hyper-V
- $ErrorActionPreference = 'Stop'
- New-Item -Path $OutputDir -ItemType Directory -Force | Out-Null
- $outFile = Join-Path $OutputDir ("hyperv-inventory-{0}-{1}.csv" -f $ComputerName, (Get-Date -Format yyyyMMdd-HHmm))
- # Sum file sizes across a differencing-disk chain (.avhdx -> parent -> ... -> base)
- function Get-VhdChainBytes {
- param([string]$Path)
- $total = 0
- while ($Path) {
- $v = Get-VHD -ComputerName $ComputerName -Path $Path -ErrorAction SilentlyContinue
- if (-not $v) { Write-Warning "Could not read VHD: $Path"; break }
- $total += $v.FileSize
- $Path = $v.ParentPath
- }
- $total
- }
- $rows = Get-VM -ComputerName $ComputerName | ForEach-Object {
- $vm = $_
- $nics = Get-VMNetworkAdapter -VM $vm
- $disks = @(Get-VMHardDiskDrive -VM $vm | Where-Object Path) # skips passthrough disks
- $vhds = $disks | ForEach-Object { Get-VHD -ComputerName $ComputerName -Path $_.Path -ErrorAction SilentlyContinue }
- $vlans = $nics | ForEach-Object {
- $vl = Get-VMNetworkAdapterVlan -VMNetworkAdapter $_
- if ($vl.OperationMode -eq 'Access') { $vl.AccessVlanId } else { $vl.OperationMode }
- }
- $ips = @($nics.IPAddresses)
- [pscustomobject]@{
- Host = $ComputerName
- VMName = $vm.Name
- State = $vm.State
- Generation = $vm.Generation
- vCPU = $vm.ProcessorCount
- MemoryGB = [math]::Round($vm.MemoryAssigned / 1GB, 1)
- Switch = ($nics.SwitchName | Select-Object -Unique) -join ', '
- VLAN = ($vlans -join ', ')
- MAC = ($nics.MacAddress) -join ', '
- IPv4 = ($ips | Where-Object { $_ -match '^\d+\.\d+\.\d+\.\d+$' }) -join ', '
- IPv6 = ($ips | Where-Object { $_ -match ':' -and $_ -notmatch '^fe80' }) -join ', '
- Disks = $disks.Count
- DiskPaths = ($disks.Path) -join '; '
- ProvisionedGB = [math]::Round((($vhds | Measure-Object Size -Sum).Sum) / 1GB, 1)
- UsedGB = [math]::Round((($disks | ForEach-Object { Get-VhdChainBytes $_.Path } | Measure-Object -Sum).Sum) / 1GB, 1)
- Checkpoints = @(Get-VMSnapshot -VM $vm).Count
- KVP = (Get-VMIntegrationService -VM $vm | Where-Object { $_.Name -match 'Key-Value|Data Exchange' }).Enabled -join ''
- }
- }
- $rows | Sort-Object VMName | Export-Csv -Path $outFile -NoTypeInformation -Encoding UTF8
- $rows | Sort-Object VMName | Format-Table VMName, State, IPv4, ProvisionedGB, UsedGB, Checkpoints -AutoSize
- "Total used: {0} GB across {1} VMs" -f ([math]::Round(($rows | Measure-Object UsedGB -Sum).Sum, 1)), @($rows).Count
- "CSV written to $outFile"
Pasted 2026-09-25 16:02:38
Short link:
Short link:
Recent Public Pastes