Location:
State:
Carrier
Country
Status

This worked.


Before I learned that VHDX expanding disks do not release space, many of these have swelled way beyond what is used of needed because I did a defrag. Defrag will use temporary space to store files parts being defragged. I expected defrag to make fragmented files use contiguous space and to move all of the files to the beginning of the VHDX disk. To emphasize my ignorance I expected defrag to truncate to unused space at the end of the disk.

What really happens is that defrag extends expanding VHDX disks as a temporary area to make files contiguous and as temporary space to squeeze out embedded free space. The new extensions are never released to the host physical disk. Defragging a VHDX extended space disk will result in allocating significant more unused physical space. As an example a 100gb fragmented expanding VHDX disk once defragged may end up actually expanding to over 300gb of real space.

A old version of Virtual PC came with a compactor.ISO utility that when run against a VHD, would squeeze all unused space to the end of the VHD disk. You could then truncate the trailing free space leaving your VHD file physically smaller. Microsoft provides no tool (I know of) that will accomplish the physical shrinking of VHDX disks. The problem may apply to VHD disks as well, but I am now using VHDX virtual disks.

Does anyone have the necessary expertise of PowerShell to script making VHDX disk files contiguous, squeezing all the unused space to the end of the VHDX disk, and then truncating the trailing free space to physically shrink virtual disks.

Just take the edit disk option from the Hyper-V management console, select your disk and then the option compact.



If you want to use powershell instead of the UI you could do this:
Code:
Mount-VHD<enter path to vhdx file> -ReadOnlyOptimize-VHD<enter path to vhdx file> -Mode fullDismount-VHD<enter path to vhdx file>
If your vhdxis not NTFS (Linux for example) you need to zero out free space first. With NTFS (Windows) you need not.

Before you do the above, use sdelete (SDelete) to zero out all the unused bits on the virtual disk. This will give you a smaller file than when you just do a compact straight away.

sdelete has to be run inside the guest OS, of course.

Before you do the above, use sdelete (SDelete) to zero out all the unused bits on the virtual disk. This will give you a smaller file than when you just do a compact straight away.

sdelete has to be run inside the guest OS, of course.
You do not need to do this with NTFS vhdx - just defrag and compact. Compacting a Dynamically Expanding virtual hard disk in Windows Server 2012 - Ask the Core Team - Site Home - TechNet Blogs

You do not need to do this with NTFS vhdx - just defrag and compact. Compacting a Dynamically Expanding virtual hard disk in Windows Server 2012 - Ask the Core Team - Site Home - TechNet Blogs
Thanks for the information!

I now use VMware player, and I still need to do this there, even when using NTFS.

A while back, when I did use Hyper-V, I noticed that running sdelete inside the guest OS still did a better job than when I only ran compact on it. Maybe it's gotten better? At least, thanks for mentioning this! It's again one thing less to do.

I have 2 VM's running Windows 10 Pro (both 10240 and both compacted and minimised as best I could)

Hyper-V VM running on Windows 10 host without Office is 5.45GB according to Windows file explorer and the vhdx is 8.16GB

VMware Fusion (latest version) VM running on OSX host with Office 2016 is 8.35GB according to Windows file explorer and the vmdk is 11.1 GB

To be honest I don't really trust any of these numbers as whenever I look in a different place I get a different answer...How much disk am I using? - Windows 10 blog

I didn't run sdelete on VMware (actually I forgot, thanks for reminding me). I will do and see if it helps any.

mount and defrag (optimize) vhd
then type
diskpart
select vdisk file="X:NAME.vhd"
Compact vdisk
exit

The solution from Rudy Mas worked as I expected.

I have not test kuhi's solution yet.

This worked.