Clean up unused Hyper-V disks with PowerShell

By | November 19, 2022

At times, you may find that orphaned vhdx and avhdx files are filling up your physical disk. You may have deleted the virtual machines in the Hyper-V console earlier, but their disks were never cleaned up. The script below lists all vhdx and avhdx files in a certain location and checks in Hyper-V if they appear in the configuration of any of the VMs. If none of the files in a certain folder are listed as found it’s a strong indication that they are no longer needed. You should check the last write time in addition.

Mind that it is not the purpose of the script to check if any avhdx files (differencing files created by Checkpoints) are obsolete but to determine if the vhdx and any avhdx files can be removed.

Also, before deleting anything, be sure to validate the result of the script. Better move the disks to a temporary location first, make yourself a note of the source folder and check if all VMs are still working before the final deletion. A backup will give you additional certainty that you don’t lose any machines that are still required.

Based on the output of the script, here’s an example of files that can be deleted:

If you look at the files in the folder E:\MachineRoom\TP2001, you see that none of them has been found in any Hyper-V configuration. An example of a VM that is still active is MAX8014 located in E:\MachineRoom\MAX8014: As you see E:\MachineRoom\MAX8014\MAX8014\Virtual Hard Disks\MAX8014_ED13FC88-69B1-4A16-862F-70CFC0BEEEC4.avhdx has been found. If you check the machine in Hyper-V, it confirms the result, thus don’t touch any files in E:\MachineRoom\MAX8014.

 

#Hyper-V VM CleanUp helper
#V1.0, Nov. 2022
#This script is provided "AS-IS" with no warrenties


$vhdxLocation = 'E:\MachineRoom'

$vhdxs = Get-VM -VMName * | Select-Object VMId | Get-VHD
#Get files on disk. Filter alloes search for vhdx and avhdx
$vhdxsOnDisk = Get-ChildItem -Path $vhdxLocation -Filter *.*vhdx -Recurse -ErrorAction SilentlyContinue -Force

foreach ($vhdxod in $vhdxsOnDisk){

$PathOnDisk = ([string]$vhdxod.Directory + '\' + $vhdxod.Name)
$LastWriteTime = $vhdxod.LastWriteTime.ToString("yyyy-MM-dd")
$Size = ([string] $vhdxod.Length/(1024*1024))

$found = $false
foreach($vhdx in $vhdxs){

#Write-Host $vhdx.Path -BackgroundColor DarkBlue -ForegroundColor yellow

if($vhdx.Path -eq $PathOnDisk)
{
#Write-Host $vhdxod.Directory -BackgroundColor DarkGreen -ForegroundColor White
$found = $true
break
}
else
{
#Write-Host $vhdxod.Directory -BackgroundColor DarkYellow -ForegroundColor White
$found = $false
}
}
if($found)
{
Write-Host ('Found: ' + $PathOnDisk + ' Last write time: ' + $LastWriteTime + ' SizeInMB: ' + $Size) -BackgroundColor Green -ForegroundColor Black
}
else
{
Write-Host ("Not found: " +$PathOnDisk + ' Last write time: ' + $LastWriteTime + ' SizeInMB: ' + $Size) -BackgroundColor Yellow -ForegroundColor Blue
}
}

 

Download from Github

Links:

What is the proper way to cleanup excess .avhdx files created by Hyper-V?

https://learn.microsoft.com/en-us/answers/questions/375897/what-is-the-proper-way-to-cleanup-excess-avhdx-fil.html

Use PowerShell to Explore Old Windows VHDs

https://devblogs.microsoft.com/scripting/use-powershell-to-explore-old-windows-vhds/

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *