From my own library, my favorite Hyper-V script is the orphaned file locator. It would be nice, though, if such a script weren’t necessary. I believe that you should be able to delete a virtual machine and be done with it. Digging through the file system to collect scraps tossed to the roadside by the official tools is tedious busy work that should be done by the computer. So, I built a tool that will do that. It is not intended to replace the orphaned file locator. This script is intended to run against a virtual machine before deletion; the orphaned file locator is intended to be run at some time after. You will not be able to run this script against already-deleted systems.

A note on the script name: I debated on shadowing the built-in Remove-VM cmdlet to enhance it with features that I believed that it should have always had. In the end, I decided to choose a new name because this script deviates so far from the original cmdlet. The hard part was in choosing a verb. Microsoft has some pre-defined “approved” verbs that they’d like everyone to use. As much as I hate being boxed in, I have to admit that it’s a good idea. You can use Get-Verb to see what the approved list is. Unfortunately, that list doesn’t have anything fun like “obliterate”, “demolish”, “eradicate”, “annihilate”, etc. (but Start-GlobalThermonuclearWar is perfectly acceptable). So, following patterns that I’ve seen in other names, I chose “Clear” as the verb.

Script Features

These are the features of the script:

  • Deletes a virtual machine
  • Removes a virtual machine from its cluster
  • Removes all of a virtual machine’s files, including virtual hard disks
  • If snapshots are present, applies the oldest before doing anything — this avoids the necessity to wait on virtual hard disks to merge
  • Deletes any folders that held the virtual machine’s files IF they are empty after the deletion and IF they are not marked as important. Criteria for importance:
    • Not used as a default VM or VHD storage location by the VM’s host
    • Not used as a configuration, snapshot, or smart paging location by any other virtual machine or snapshot on the host
  • Detailed -WhatIf  support
  • Not dependent on any other PowerShell module
  • Operates on local and remote hosts

How It Works

This script is very procedural in nature. This is the process:

  1. Gather a list of everything that makes up the virtual machine: files, folders, whether or not it is clustered, and whether or not it is participating in Hyper-V Replica. If it is being replicated, that’s a hard stop. You’ll need to break the replica configuration yourself.
  2. Gather an inventory of its host: host default folders and the storage folders for its other virtual machines. This helps to ensure that we do not inadvertently delete an important folder.
  3. Stop the virtual machine if it is running. Since it’s being deleted anyway, this is a hard stop — no waiting for an orderly guest shut down. If the virtual machine is currently in a saved state, that is automatically cleared.
  4. The virtual machine is removed from the cluster, if it is highly available.
  5. The oldest snapshot, if any, is applied. That means that the current state of the virtual machine will be permanently lost — which seems like a non-issue to me, since you asked to delete it. The benefit is that you won’t have to wait for any virtual hard disks to be merged like you do when using the built-in delete operations.
  6. All snapshots, if any, are deleted.
  7. The virtual machine is deleted.
  8. Any surviving files gathered during the inventory are deleted.
  9. Any surviving folders gathered during the inventory that are not shared by other virtual machines and do not have any files or folders as children are deleted.

Note on Windows 10/Windows Server 2016 Support

I wrote this script against Windows Server 2012 R2 test systems so I have full confidence it will operate on that generation of Hyper-V. Given the timing of this article’s publication, a natural question is, “will it work on Windows 10/Windows Server 2016?” The answer is: probably. The script relies on the native functionality of Hyper-V as much as possible, meaning that most of the heavy lifting is done by the Virtual Machine Management service. Because VMMS should be handling all of the new file types, none should be left over for this script to worry about. So, as long as your system is healthy and performing like it should, a general assumption would be that this script should have the same outcome on versions 2012-2016 as well as their matching Client Hyper-V versions. If something doesn’t work, it will not recognize those new file types and will leave them and their folders behind. All that said, this script must make some assumptions about the file layout of virtual machines. I believe that these conditions carry forth well enough to 2016, but I don’t yet know that for certain. Until I know, proceed at your own risk.

Once I have a solid Windows Server 2016 environment to test with, I will update the script to check for the new file types and handle them as well.

Disclaimer

This script deletes files. That means that data loss is part of what it is designed to cause. I have done everything in my power to scope its deletions as tightly as possible to the input, but I cannot control your input nor can I ever be totally certain that a script with this level of complexity will always perform precisely as intended in every possible situation. As always, you should have good backups of everything and be extremely careful with wildcards and pipeline input.

Neither I nor Altaro Software, Ltd. accept any responsibility for anything that is done with this script. If you don’t trust it, don’t use it.

Script Source

Save this script as Clear-VM.ps1. If pasted verbatim, you call the file when you need it (ex: C:\Scripts\Clear-VM.ps1). There are instructions in the file for removing three comment markers to enable the script to be dot-sourced so that you can include it in your profile, if you like.

The script fully supports Get-Help.