Friday, November 22, 2013

Delete VMs in Windows Server 2012 and Windows Server 2012 R2 Hyper-V by a PowerShell script

In Windows Server 2012 and Windows Server 2012 R2, we can remove a VM by Hyper-V Manager or PowerShell, "Remove-VM". However, it just deleted the VM and a configuration file of that VM. It hasn't deleted the related virtual hard disk files so we need to delete the virtual hard disk files by ourself. I intended to create a PowerShell script to remove VMs and related virtual hard disk files.

Disclaimer: Make sure you do understand the script and test it in lab environment. You use this script at your own risk. If you don't understand what this script does, please don't use it in any environment. 
 
Function Delete-VM {

<#
.Synopsis
Delete virtual machines with related virtual hard disk files in a Hyper-V server.

.DESCRIPTION
This function is intended to delete virtual machines with all related virtual hard disk files in a Hyper-V Server which is installed Windows Server 2012 and Windows Server 2012 R2.

If a virtual machine is not in "Off" state , this script shows a pop-up window for Administrator deciding shut down the VM or not. After that, the script continue deleting the VM.

There is a "Force" option to shut down and delete virtual machines without confirmation for this script.

Before you using this function, it requires the Hyper-V Module for Windows PowerShell which is installed in your computer.

.Notes
Name        : Delete-VM.ps1   
Last Updated: 22-Nov-2013
Version     : 1.0
Requires    : PowerShell version 3.0 or above with Hyper-V Module for Windows PowerShell

.Link
http://terrytlslau.tls1.cc/2013/11/delete-vms-in-windows-server-2012-and.html

.Parameter Name
The virtual machine name in a Hyper-V Server.

.Parameter ComputerName
The computer name of a Hyper-V Server.

.Parameter Force
Shut down and delete virtual machines with related virtual hard disk files without confirmation window. 

.EXAMPLE
Delete-VM -Name server01

Delete a VM named server01 in current Hyper-V host.

.EXAMPLE
Delete-VM -Name server02 -ComputerName HV02

Delete a VM named server02 in the Hyper-V host, HV02.

.EXAMPLE
Delete-VM -Name server03 -Force

Shut down and delete a VM named server03 with related virtual hard disk files without any confirmation.

.EXAMPLE
Get-VM -Name Server04 | Delete-VM

Get-VM and then pass the value from pipeline to Delete-VM.
#>

[CmdletBinding(ConfirmImpact='High')]

Param (
[Parameter(Position=0,Mandatory=$True,ValueFromPipelineByPropertyName=$True,HelpMessage="Enter the VM name")]
[String[]]$Name,
[Parameter(ValueFromPipelineByPropertyName=$True)]
[String[]]$ComputerName = $env:COMPUTERNAME,
[Switch]$Force
)

Process {

ForEach ($Comp in $ComputerName) {

ForEach ($VMName in $Name) {

Try {
$VMlist_OK = $True
$VMlist = Get-VM -Name $VMName -ComputerName $Comp -ErrorAction Stop
}

Catch {
$VMlist_OK = $False
Write-Warning "The VM $VMName in the server $Comp cannot be found" 
}

If ($VMlist_OK) {
$VMHostPath = $((Get-VMHost -ComputerName $Comp).VirtualMachinePath)
$VMState = $((Get-VM -Name $VMName -ComputerName $Comp).state)
$VMPath = $((Get-VM -Name $VMName -ComputerName $Comp).path)
$VHD = $((Get-VMHardDiskDrive -VMName $VMName -ComputerName $Comp).path)

if ($Force) {

Try {

if (($VMState -eq 'Running') -or ($VMState -eq 'Paused')) {
Stop-VM -Name $VMName -ComputerName $Comp -Force                                    
Remove-VM $VMName -ComputerName $Comp -Force                                    
Invoke-command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VHD -Force}
Remove-Variable VHD

if ($VMHostPath -ne $VMPath) {                                                                    
Invoke-command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VMPath -Recurse -Force}
Remove-Variable VMPath
}

Write-Output "The VM $VMName in the server $Comp was deleted completely!!!"
} 

else {
Remove-VM $VMName -ComputerName $Comp -Force                                    
Invoke-command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VHD -Force}
Remove-Variable VHD                                    

if ($VMHostPath -ne $VMPath) {                                                                    
Invoke-command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VMPath -Recurse -Force}
Remove-Variable VMPath
}                                

Write-Output "The VM $VMName in the server $Comp was deleted completely!!!"
} 
} 

Catch {
Write-Warning "Force deleted $VMName error"
}

} 

else {

if (($VMState -eq 'Running') -or ($VMState -eq 'Paused')) {
Stop-VM -Name $VMName -ComputerName $Comp

if ((Get-VM -Name $VMName -ComputerName $Comp).uptime -gt "00:00:00") {
Write-Warning "The VM $VMName in $Comp hasn't been stopped!!! Cancel to delete VM $VMName"
Continue
}

else {
Write-Verbose "The VM $VMName in $Comp has been stopped!"
Remove-VM -Name $VMName -ComputerName $Comp

Try {
Get-VM -Name $VMName -ComputerName $Comp -ErrorAction Stop | Select -First 0
Write-Warning "The VM $VMName in the server $Comp hasn't been deleted!!! Cancel to delete VM $VMName" 
Continue
}

Catch {
Invoke-Command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VHD}
Remove-Variable VHD

if ($VMHostPath -ne $VMPath) {                                            
Invoke-Command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VMPath -Recurse}
Remove-Variable VMPath
}

Write-Output "The VM $VMName in $Comp was deleted completely!!!"
}
                                       
} 

}

else {
Write-Verbose "The VM $VMName in $Comp has been stopped!"
Remove-VM -Name $VMName -ComputerName $Comp

Try {                                    
Get-VM -Name $VMName -ComputerName $Comp -ErrorAction Stop | Select -First 0
Write-Warning "The VM $VMName in $Comp hasn't been deleted!!! Cancel to delete $VMName"
Continue
}

Catch {                                
Invoke-Command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VHD}
Remove-Variable VHD

if ($VMHostPath -ne $VMPath) {                                            
Invoke-Command -ComputerName $Comp -ScriptBlock {Remove-Item -Path $Using:VMPath -Recurse}
Remove-Variable VMPath
}

Write-Output "The VM $VMName in $Comp was deleted completely!!!"
}
                                
} 

}                  

} 

} 

} 

} # End Process

} # End function

This posting is provided “ AS IS” with no warranties, and confers no rights!

No comments:

Post a Comment