Applies To

This article applies to: Microsoft Azure Virtual Machines

1. Introduction

This article is exploring a PowerShell Script to help you to delete the Virtual Machine and all the associated resources like Disks (Boot Diagnostics Disk, OS, Data disks), Network adapters, Public IP of an Azure VM. When you delete an Azure VM, the resources allocated with the VM will remains in your Azure tenant and not deletes along with the VM. So, the users need to pay additional cost of these resources, even though the resources are not used with the VM. Also, in a large infrastructure, identifying the resources which were the part of the VM is very difficult and to delete manually.

2. Notes

  1. The script covers only the resources as indicated above and you may further modify the script to delete other resources also. The script will not delete the network security group, Storage Account and Virtual Network as there can be other VMs attached to these resources
  2. When you start the script, the user will be prompted to enter the VM Name to be entered. The script can be further modified to accommodate list of VMs from a csv file to handle more VMs to be deleted by the script 

3. Procedure to be followed

  1. Copy the full script below in to a notepad and save as .ps1 file
  2. Open PowerShell as Administrator
  3. Connect your Azure tenant using PowerShell. Please refer the link to check, how you can connect Azure Tenant using PowerShell
  4. Run the ps1 script in PowerShell
  5. Script will prompt to enter the VM Name. Enter the correct VM name and sit relax until the script completes the full deletion of all your resources
  6. The script will print the progress of each resources deletion in PowerShell to inform the user about the progress

4. PowerShell Script

Write-Host -NoNewline -ForegroundColor Green "Please enter the VM name you would like to remove:"
$VMName = Read-Host
$vm = Get-AzVm -Name $VMName
if ($vm) {
$RGName=$vm.ResourceGroupName
Write-Host -ForegroundColor Cyan 'Resource Group Name is identified as-' $RGName
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
Write-Host -ForegroundColor Cyan 'Marking Disks for deletion...'
$tags = @{"VMName"=$VMName; "Delete Ready"="Yes"}
$osDiskName = $vm.StorageProfile.OSDisk.Name
$datadisks = $vm.StorageProfile.DataDisks
$ResourceID = (Get-Azdisk -Name $osDiskName).id
New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
if ($vm.StorageProfile.DataDisks.Count -gt 0) {
    foreach ($datadisks in $vm.StorageProfile.DataDisks){
    $datadiskname=$datadisks.name
    $ResourceID = (Get-Azdisk -Name $datadiskname).id
    New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
    }
}
if ($vm.Name.Length -gt 9){
    $i = 9
    }
    else
    {
    $i = $vm.Name.Length - 1
}
$azResourceParams = @{
 'ResourceName' = $VMName
 'ResourceType' = 'Microsoft.Compute/virtualMachines'
 'ResourceGroupName' = $RGName
}
$vmResource = Get-AzResource @azResourceParams
$vmId = $vmResource.Properties.VmId
$diagContainerName = ('bootdiagnostics-{0}-{1}' -f $vm.Name.ToLower().Substring(0, $i), $vmId)
$diagSaRg = (Get-AzStorageAccount | where { $_.StorageAccountName -eq $diagSa }).ResourceGroupName
$saParams = @{
  'ResourceGroupName' = $diagSaRg
  'Name' = $diagSa
}
Write-Host -ForegroundColor Cyan 'Removing Boot Diagnostic disk..'
if ($diagSa){
Get-AzStorageAccount @saParams | Get-AzStorageContainer | where {$_.Name-eq $diagContainerName} | Remove-AzStorageContainer -Force
}
else {
Write-Host -ForegroundColor Green "No Boot Diagnostics Disk found attached to the VM!"
}
Write-Host -ForegroundColor Cyan 'Removing Virtual Machine-' $VMName 'in Resource Group-'$RGName '...'
$null = $vm | Remove-AzVM -Force
Write-Host -ForegroundColor Cyan 'Removing Network Interface Cards, Public IP Address(s) used by the VM...'
foreach($nicUri in $vm.NetworkProfile.NetworkInterfaces.Id) {
   $nic = Get-AzNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $nicUri.Split('/')[-1]
   Remove-AzNetworkInterface -Name $nic.Name -ResourceGroupName $vm.ResourceGroupName -Force
   foreach($ipConfig in $nic.IpConfigurations) {
     if($ipConfig.PublicIpAddress -ne $null){
     Remove-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name $ipConfig.PublicIpAddress.Id.Split('/')[-1] -Force
     }
    }
}
Write-Host -ForegroundColor Cyan 'Removing OS disk and Data Disk(s) used by the VM..'
Get-AzResource -tag $tags | where{$_.resourcegroupname -eq $RGName}| Remove-AzResource -force | Out-Null
Write-Host -ForegroundColor Green 'Azure Virtual Machine-' $VMName 'and all the resources associated with the VM were removed sucesfully...'
}
else{
Write-Host -ForegroundColor Red "The VM name entered doesn't exist in your connected Azure Tenant! Kindly check the name entered and restart the script with correct VM name..."
}

5. Script Progress example

Following PowerShell screens shows some of the example script output.

1. Invalid VM name handling

2. Successful deletion of the VM and all associated resources


6. Conclusion

The script is very useful to delete the VM and associated resources with minimal user intervention.