Shrinking a VHD in Windows 8 - fast!

Shrinking a VHD in Windows 8 - fast!

Rate This
  • Comments 13


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:

PowerShell resize

This whole process took under a minute and was completed without needing to start the virtual machine.

Cheers,
Ben

Leave a Comment
  • Please add 1 and 2 and type the answer here:
  • Post
  • It works only with VHDX right?

  • 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" ?

  • Ah this was better than my solution :-)

  • I also interested in the answer to the question of Alex Kibkalo.

  • 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.

  • 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,

    Ben

  • 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?

  • Will the resize work if you don't defrag the drive before you resize it?

  • Hello and thanks for the info.Any ideas why i get Resize-Partition : Size Not Supported when i use Resize-Partition ?

    Thanks!

  • 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)*1024*1024*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.

  • 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!

  • how would i shrink or compact a linux vhd?

  • 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!

Page 1 of 1 (13 items)