Shrinking a VHD in Windows 8 - fast!
A couple of days ago I talked about how it was much easier to shrink a virtual hard disk in Windows 8. But after writing that blog post – I spent some time playing around with PowerShell and found that there was an even better option.
Instead of logging into a running virtual machine, doing some work, shutting it down and completing the operation. You can do everything from PowerShell in Hyper-V if the virtual machine is shutdown first.
The process that I figured out is as follows:
- get-vm <vmname> | select ID | get-vhd | select path
- This command will get you the virtual hard disk path and file name for each virtual hard disk in the virtual machine. Obviously you can skip this if you already know it.
- mount-vhd <vhdname> –passthru | get-disk | get-partition | get-volume
- This will mount the virtual hard disk in the management operating system, and let you know the drive letter that was assigned to it.
- resize-partition –driveletter <driveletter> –size <newsize>
- This will resize the partition inside the virtual hard disk
- dismount-vhd <vhdname>
- Dismount the virtual hard disk after shrinking the partition
- resize-vhd <vhdname> –ToMinimumSize
- Now shrink the virtual hard disk to match the new size
Here is a screenshot of me resizing a virtual hard disk from 50GB to 30GB on a virtual machine:
This whole process took under a minute and was completed without needing to start the virtual machine.
Cheers,
Ben
Comments
Anonymous
May 10, 2012
It works only with VHDX right?Anonymous
May 10, 2012
Great topic! That works with both VHD and VHDX. Ben, can you try to explain, what (technically) prevents to do that for a running VM, by some other means? I can resize partition on the running VM - even a system partition. With Win8/WS2012 we have block level storage access. We can now merge snapshots online and extend disks online. Why can't I shrink online "-ToMinimumSize" ?Anonymous
May 13, 2012
Ah this was better than my solution :-)Anonymous
May 15, 2012
I also interested in the answer to the question of Alex Kibkalo.Anonymous
June 02, 2012
Ben, I'm just installing Win 8 64bit on my laptop. I was running vmplayer on my previous installation of Win 7 Ultimate. I checked and you haven't done an update on how to move a VMDK to Hyper-V Client since 2007. Maybe it's time for this topic again in the wake of Win8 having Hyper-V now.Anonymous
June 04, 2012
Alex / Denis - No technical reason - other than dealing with the limits of time and what we can develop and test in a given release. Craig - I will put it on my list. My biggest problem is that I do not have any VMDKs to test this with :-) Cheers, BenAnonymous
July 01, 2012
Hmmm, the dismount-vhd & resize-vhd cmdlets are not found when I try to run this under the Win8 RC bits. Are these only found under Server 2012 PowerShell?Anonymous
October 13, 2013
Will the resize work if you don't defrag the drive before you resize it?Anonymous
October 22, 2013
Hello and thanks for the info.Any ideas why i get Resize-Partition : Size Not Supported when i use Resize-Partition ? Thanks!Anonymous
November 09, 2013
Tasos, I also had the "Size Not Supported" problem when resizing the partition and about pulled out what little hair I have left trying to figure this out. My solution works but I am not sure exactly what is going on, and it is not elegant. Maybe Ben can enlighten us. I had to round up the partition size to the nearest GB, then had to run the repartition at least 3 times! My code snippet that seems to work is below: #round up to next GB $MinSize = (Get-PartitionSupportedSize -DriveLetter $OSVol.DriveLetter).SizeMin $MinSize = [math]::Ceiling($MinSize/1024/1024/1024)10241024*1024 'Minimum partition size: {0}' -f $MinSize write-host "Defragmenting volume" Optimize-Volume -DriveLetter $OSVol.DriveLetter -ReTrim -Defrag write-host "Shrinking Partition" $ErrorActionPreference = "SilentlyContinue" $i = 0 do { $error.clear() $i++ resize-partition -DriveLetter $OSVol.DriveLetter -size $MinSize } while (($error.count -gt 0) -and ($i -lt 5)) $ErrorActionPreference = "Continue" if ($error.count -gt 0) { write-host "Partition could not be shrunk - terminating" dismount-vhd $vhd exit } As you can see I am defragmenting the volume as well which may not be complete when the resize-partition runs (a wild guess). I have tried to determine what may be preventing the resize-partition from running, but do not see any disk status indications as to what is happening.Anonymous
November 18, 2013
get-vm was returning an empty list for me. You need to make sure you fire up power shell with elevated rights before they show up... ie. "Run as Administrator" After that worked a treat, cheers!Anonymous
January 01, 2014
how would i shrink or compact a linux vhd?Anonymous
January 29, 2014
This worked beautifully. I needed to get machines up to Azure IaaS and had to reduce my 150GB volumes down. Not able to find the VHDResizer I stumbled on this. FYI, I had VHD files and not VHDX so the last cmdlet with the -ToMinimumSize only works on VHDX but the VHD still gets resized without running that cmdlet. Thanks!Anonymous
November 04, 2014
I need to shrink the VHD size, not the size of the file.