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.
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.
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.
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.
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.
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:
Dismount-DiskImage -ImagePath 'C:ClusterStorageCSV1Virtual Hard Disksvirtualharddisk.vhdx'
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:
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:
You can also use Failover Cluster Manager, on the Storage/Disks node:
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.
Alternatively, you can use PowerShell:
Move-ClusterSharedVolume -Name csv1 -Node svhv2
If you don’t want to tell it which node to place the CSV on, simply omit the Node parameter:
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.