When you use the built-in Hyper-V tools (Hyper-V Manager and PowerShell) to delete a virtual machine, all of its virtual hard disks are left behind. This is by design and is logically sound. The configuration files are components of the virtual machine and either define it or have no purposeful existence without it; the virtual hard disks are simply attached to the virtual machine and could just as easily be attached to another. After you delete the virtual machine, you can manually delete the virtual hard disk files. Usually. Sometimes, when the VHD is placed on a cluster shared volume (CSV), you might have some troubles deleting it. The fix is simple.

Symptoms

There are a few ways that this problem will manifest. All of these conditions will be applicable, but the way that you encounter them is different.

Symptom 1: Cannot Delete a VHDX on a CSV Using Windows Explorer on the CSV’s Owner Node

When using Windows Explorer to try to delete the file from the node that own the CSV, you receive the error: The action can’t be completed because the file is open in System. Close the file and try again.

System has VHD Open

System has VHD Open

 

Note: this message does sometimes appear on non-owner nodes.

Symptom 2: Cannot Delete a VHDX on a CSV Using Windows Explorer on a Non-Owning Node

When using Windows Explorer to try to delete the file from a node other than the CSV’s owner, you receive the error: The action can’t be completed because the file is open in another program. Close the file and try again.

Another Program has the VHD Open

Another Program has the VHD Open

 

Note: non-owning nodes do sometimes receive the “System” message from symptom 1.

Symptom 3: Cannot Delete a VHDX on a CSV Using PowerShell

The error is always the same from PowerShell whether you are on the owning node or not: Cannot remove item virtualharddisk.vhdx: The process cannot access the file ‘virtualharddisk.vhdx’ because it is being used by another process.

Another Process has the CSV

Another Process has the CSV

 

Symptom 4: Cannot Delete a VHDX on a CSV Using the Command Prompt

The error message from a standard command prompt is almost identical to the message that you receive in PowerShell: The process cannot access the file because it is being used by another process.

Another Process has the VHD

Another Process has the VHD

 

Solution

Clean up is very simple, but it comes with a serious warning: I do not know what would happen if you ran this against a VHD that was truly in use by a live virtual machine, but you should expect the outcome to be very bad.

Open an elevated PowerShell prompt on the owner node and issue Dismount-DiskImage:

You do not need to type out the -ImagePath parameter name but you must fully qualify the path! If you try to use a relative path with Dismount-DiskImage or any of the other disk image manipulation cmdlets, you will be told that The system cannot find the file specified:

DiskImage Cmdlet Fails on Relative Paths

DiskImage Cmdlet Fails on Relative Paths

 

Once the cmdlet returns, you should be able to delete the file without any further problems.

If you’re not sure which node owns the CSV, you can ask PowerShell, assuming that the Failover Cluster cmdlets are installed:

CSV Owner in PowerShell

CSV Owner in PowerShell

 

You can also use Failover Cluster Manager, on the Storage/Disks node:

CSV Owner in Failover Cluster Manager

CSV Owner in Failover Cluster Manager

 

Other Cleanup

Make sure to use Failover Cluster Manager to remove any other mention of the virtual machine. Look on the Roles node. These resources are not automatically cleaned up when the virtual machine is deleted. Try to be in the habit of removing cluster resources before deleting the related virtual machine, if possible. I assume that for most of us, deleting a virtual machine is a rare enough occurrence that it’s easy to overlook things like this. I do know that the problem can occur even if the objects are deleted in the “proper” order, so this is not the root cause.

Alternative Cleanup Approaches

The above solution has worked for me every time, but it’s a very rare event without a known cause, so it’s impossible for me to test every possibility. There are two other things that you can try.

Move the CSV to Another Node

Moving the CSV to another node might break the lock from the owning node. This has worked for me occasionally, but not as reliably as the primary method described above.

In Failover Cluster Manager, right-click the CSV, expand Move, then click one of the two options. Best Possible Node will choose where to place the CSV for you; Select Node will give you a dialog for you to choose the target.

Move CSV in Failover Cluster Manager

Move CSV in Failover Cluster Manager

 

Alternatively, you can use PowerShell:

If you don’t want to tell it which node to place the CSV on, simply omit the Node  parameter:

Move CSV in PowerShell

Move CSV in PowerShell

 

Rolling Cluster Reboot

The “nuclear” option is to reboot each node in the cluster, starting with the original owner node. If this does not work, then the disk image is truly in use somewhere and you need to determine where.