Hyper-V BIN file removal and reclaiming storage space

Background on Files in Hyper-V

.XML Contains the VM configuration.

.VHD and .VHDX: The virtual disks that hold the current virtual disk data, including partitions and file systems.

.BIN Contains the memory of a virtual machine or snapshot that is in a saved state.

.VSV Contains VM’s saved state.

.AVHD and .AVHDX Differencing virtual disks, commonly used for Hyper-V checkpoints.

BIN Files

Location, Size and Purpose

The BIN file gets created in the virtual machine folder of the virtual machine is equal to the size of the memory of the virtual machine and is a placeholder to save the virtual machine state in the event that the Hyper-V host shut down.

The BIN file contains the memory of a VM and is located inside the GUID folder. If the VM in powered off state, there will be no BIN file present. This file is the equal to the size of the VM’s memory provisioning in Hyper-V Manger.

History

In Windows Server 2008 and Windows Server 2008 R2 starting a virtual machine would result in Hyper-V creating a .BIN file which matched the size of the memory assigned to the virtual machine. Microsoft did this to ensure that we always had enough disk space available to create a saved state (which is particularly critical if the physical computer is shutting down – and the virtual machine is configured to save state when the physical computer shuts down).

The BIN file is idle while the virtual machine is powered on. It is pre-allocated so that the space is guaranteed to be available if needed and quicker to response to a save action.

Today

To address this, since Windows Server 2012 Microsoft made a simple change. Hyper-V only creates the .BIN file if you choose “Save the virtual machine state” as the Automatic Stop Action for the virtual machine. If you choose “Turn off the virtual machine” or “Shut down the guest operating system”, BIN file will not be created.

It is still possible to save the state manually if there is enough room for the file. The Automatic Stop Action setting in only applicable when Physical computer shutdown.

By default, all virtual machines have the Automatic Stop Action of “Save” which means the state of the virtual machine saved to disk. However, the best practice is once Integration Services are enabled the Automatic Stop Action should be changed to “Shut down the guest operating system”, which performs a clean shutdown and no longer needs the BIN file to save the memory content to.

Considerations

Keeping the .BIN file is not recommended for a cluster environment. VM’s configured for High Availability, in case of Physical computer shutdown, will failover to another node so there is no advantage in having it.

Consider choosing BIN file if Hyper-v Servers are not in cluster (standalone) and no constraints with storage space. VM move into saved state only when Hyper-v Host is gracefully shutdown and VM will not move to save state in case Hyper-v host is unexpected shutdown/restart.

Microsoft does not recommend keeping VM in saved state for the applications like Domain Controllers, Database, etc… Changing the Automatic Stop Action to “Shut down” from “Save state” is the recommended state.

Checking the footprint of the BIN files

$Path = "" # Path to VM storage location
$Items = Get-ChildItem -Path $Path -Recurse -Filter *.bin
$TotalSize = 0
Foreach ($I in $Items)
{
    $Size_GB = [math]::Round($I.Length/1GB,4)
    $TotalSize+=$Size_GB
}
Write-Output "Total size of .BIN files: $TotalSize"

 

Steps for removing BIN File

In Hyper-V Manager

  1.  Shutdown the virtual machine
  2. Go to VM Settings ->Automatic Stop Action -> Change the Option from “Save the virtual Machine state” to “Shut down the guest operating system”
  3. Start the virtual machine.

In PowerShell with Virtual Machine Manager

$VMStopActionOld = "SaveVM"
$VMMServer    = "" # VMM Server Name
$HVlogin = Get-Credential

Import-Module 'virtualmachinemanager\virtualmachinemanager.psd1' # import VMM module
Get-SCVMMServer -ComputerName $VMMServer -Credential $HVlogin | out-null # connect to VMM server
$VirtualMachines = Get-SCVirtualMachine -VMMServer $VMMServer 
Write-Output "$(Get-Date) Getting Virtual Machines" # notify process is starting
Foreach ($VirtualMachine in $VirtualMachines) # loop through the rows in the CSV file 
{
    $VMName = $VirtualMachine.Name
    $VMStopAction = $VirtualMachine.StopAction
    If ($VMStopAction -eq $VMStopActionOld) # set the flag on what types of servers to update
    {   
        $ProcessVM = $true
        Write-Output "$(Get-Date) $VMName set to be processed. Stop Action currently $VMStopAction"
    }
    Else
    {
        $ProcessVM = $false # criteria not met
        Write-Output "$(Get-Date) $VMName will be skipped. Stop Action currently $VMStopAction"
    }
    If ($ProcessVM -eq $true)
    {
        Write-Output "$(Get-Date) $VMName starting configuration change for Stop Action."
        $VM = Get-SCVirtualMachine -Name $VMName # get the server object
        $VM | Read-SCVirtualMachine  | out-null # refresh the state of the vm before proceeding
            If ($VM.Status -eq "PowerOff") # some will be turned off already, don't turn them back on.
            {
                Write-Output "$(Get-Date) $VMName already shutdown."
                Write-Output "$(Get-Date) $VMName will be updated but not started once complete."
                Write-Output "$(Get-Date) $VMName is being updated"
                Set-SCVirtualMachine -VM $VM -StopAction ShutdownGuestOS | out-null # update the  value
            }
            Else
            {
                Write-Output "$(Get-Date) $VMName waiting to shutdown."
                Stop-SCVirtualMachine -vm $VM | out-null # shutdown the server
                While (($VM).Status -ne "PowerOff") 
                {
                    Start-Sleep -Seconds 5 # wait while the server shuts down
                }
                Write-Output "$(Get-Date) $VMName shutdown, updating Stop Action setting."
                Set-SCVirtualMachine -VM $VM -StopAction ShutdownGuestOS  | out-null # update the CPU value
                Start-Sleep -Seconds 3 # Give VMM time to reconfigure the CPU setting
                Write-Output "$(Get-Date) $VMName starting up." 
                Start-SCVirtualMachine -vm $VM  | out-null # turn the VM back on
            }
    }
}