# Connect-VIServer "your-vcenter"
$results = @()
$tolerancePercent = 10 # Matching tolerance ±10%
foreach ($vm in Get-VM | Where-Object { $_.PowerState -eq "PoweredOn" }) {
Write-Host "Processing VM: $($vm.Name)"
$guest = Get-VMGuest -VM $vm -ErrorAction SilentlyContinue
$guestDisks = $guest.Disks
$hardDisks = Get-HardDisk -VM $vm
$vmView = Get-View $vm.Id
$devices = $vmView.Config.Hardware.Device
$matchedGuestIndexes = @()
foreach ($hd in $hardDisks) {
$dev = $devices | Where-Object { $_.DeviceInfo.Label -eq $hd.Name }
if (-not $dev) { continue }
$controller = $devices | Where-Object { $_.Key -eq $dev.ControllerKey }
$scsiID = "$($controller.BusNumber):$($dev.UnitNumber)"
$capacityGB = [math]::Round($hd.CapacityKB / 1MB, 2)
$storageFormat = $hd.StorageFormat
$vmdkPath = $hd.Filename
# Attempt match by guest disk size within tolerance
$matchedDisk = $null
$matchIndex = -1
for ($i = 0; $i -lt $guestDisks.Count; $i++) {
if ($matchedGuestIndexes -contains $i) { continue }
$guestCapGB = [math]::Round($guestDisks[$i].Capacity / 1GB, 2)
$lowerBound = $capacityGB * (1 - $tolerancePercent / 100)
$upperBound = $capacityGB * (1 + $tolerancePercent / 100)
if ($guestCapGB -ge $lowerBound -and $guestCapGB -le $upperBound) {
$matchedDisk = $guestDisks[$i]
$matchIndex = $i
break
}
}
if ($matchedDisk) {
$matchedGuestIndexes += $matchIndex
$guestCap = [math]::Round($matchedDisk.Capacity / 1GB, 2)
$guestFree = [math]::Round($matchedDisk.FreeSpace / 1GB, 2)
$guestUsed = [math]::Round($guestCap - $guestFree, 2)
$guestPath = $matchedDisk.Path
} else {
$guestCap = $guestFree = $guestUsed = $guestPath = "Unmatched"
}
$results += [PSCustomObject]@{
VMName = $vm.Name
HardDisk = $hd.Name
SCSI_ID = $scsiID
VMDKPath = $vmdkPath
VMDKCapacityGB = $capacityGB
StorageFormat = $storageFormat
GuestDrive = $guestPath
GuestCapacityGB = $guestCap
GuestFreeGB = $guestFree
GuestUsedGB = $guestUsed
}
}
# Add remaining unmatched guest drives
for ($j = 0; $j -lt $guestDisks.Count; $j++) {
if ($matchedGuestIndexes -contains $j) { continue }
$gd = $guestDisks[$j]
$results += [PSCustomObject]@{
VMName = $vm.Name
HardDisk = ""
SCSI_ID = ""
VMDKPath = ""
VMDKCapacityGB = ""
StorageFormat = ""
GuestDrive = $gd.Path
GuestCapacityGB = [math]::Round($gd.Capacity / 1GB, 2)
GuestFreeGB = [math]::Round($gd.FreeSpace / 1GB, 2)
GuestUsedGB = [math]::Round(($gd.Capacity - $gd.FreeSpace) / 1GB, 2)
}
}
}
# Display results
$results | ft -a
# Export if needed
# $results | Export-Csv -path c:\temp\Matched_VM_VMDK_GuestDrive_Report.csv -NoTypeInformation