Functions/Remove-AHVM.ps1

#Author: Adam Bertram
#Link: https://github.com/adbertram/Random-PowerShell-Work/blob/master/Azure/Remove-AzrVirtualMachine.ps1
#Date: 10/16/2020

#Deletes the VM and the associated resources
#I like the code that was provided but I did some modifying to get it up to date and working as desired for my needs
function Remove-AHVM {
    <#
    .SYNOPSIS
        This function is used to remove any Azure VMs as well as any attached disks. By default, this function creates a job
        due to the time it takes to remove an Azure VM.
        
    .EXAMPLE
        PS> Get-AzVm -Name 'BAPP07GEN22' | Remove-AzrVirtualMachine
    
        This example removes the Azure VM BAPP07GEN22 as well as any disks attached to it.
        
    .PARAMETER VMName
        The name of an Azure VM. This has an alias of Name which can be used as pipeline input from the Get-AzureRmVM cmdlet.
    
    .PARAMETER ResourceGroupName
        The name of the resource group the Azure VM is a part of.
    
    .PARAMETER AsJob
        If you would rather have a job created to remove the VM in the background, use this switch parameter and specify credentials
        with the Credential switch.

    .PARAMETER Credential
        Credentials to create the job if using -AsJob
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param
    (
        [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias('Name')]
        [string]$VMName,
        
        [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string]$ResourceGroupName,

        [Parameter()]
        [pscredential]$Credential,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [switch]$AsJob
        
    )

    process {
        $scriptBlock = {
            param ($VMName,
                $ResourceGroupName)
            $commonParams = @{
                'Name'              = $VMName;
                'ResourceGroupName' = $ResourceGroupName
            }
            $vm = Get-AzVm @commonParams
            
            #region Remove the boot diagnostics disk
            if ($vm.DiagnosticsProfile.bootDiagnostics) {
                Write-Verbose -Message 'Removing boot diagnostics storage container...'
                $diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
                Get-AzStorageAccount -Name $diagSa -ResourceGroupName $vm.ResourceGroupName | Remove-AzStorageAccount -Force
            
            }
            #endregion


            Write-Verbose -Message 'Removing the Azure VM...'
            $null = $vm | Remove-AzVM -Force
            Write-Verbose -Message 'Removing the Azure network interface...'
            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 ($Null -ne $ipConfig.PublicIpAddress) {
                        Write-Verbose -Message 'Removing the Public IP Address...'
                        Remove-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name $ipConfig.PublicIpAddress.Id.Split('/')[-1] -Force
                    } 
                }
                $nsg = Get-AzNetworkSecurityGroup | Where-Object { $_.Id -eq $nic.NetworkSecurityGroup.Id }
                If ($nsg.NetworkInterfaces.Count -eq 0) {
                    Write-Verbose "No other VMs using $($nsg.name) - deleting $($nsg.name)"
                    $nsg | Remove-AzNetworkSecurityGroup -Force
                }
            } 

                        
            ## Remove the OS disk
            Write-Verbose -Message 'Removing OS disk...'
            if ('Uri' -in $vm.StorageProfile.OSDisk.Vhd) {
                ## Not managed
                $osDiskId = $vm.StorageProfile.OSDisk.Vhd.Uri
                $osDiskContainerName = $osDiskId.Split('/')[-2]

                ## TODO: Does not account for resouce group
                $osDiskStorageAcct = Get-AzStorageAccount | Where-Object { $_.StorageAccountName -eq $osDiskId.Split('/')[2].Split('.')[0] }
                $osDiskStorageAcct | Remove-AzStorageBlob -Container $osDiskContainerName -Blob $osDiskId.Split('/')[-1]

                #region Remove the status blob
                Write-Verbose -Message 'Removing the OS disk status blob...'
                $osDiskStorageAcct | Get-AzStorageBlob -Container $osDiskContainerName -Blob "$($vm.Name)*.status" | Remove-AzStorageBlob
                #endregion
            }
            else {
                ## managed
                #Get-AzDisk | Where-Object { $_.ManagedBy -eq $vm.Id } | Remove-AzDisk -Force
                Get-AzDisk | Where-Object { $_.id -eq $vm.StorageProfile.OsDisk.ManagedDisk.Id } | Remove-AzDisk -Force
            }
            
            ## Remove any other attached disks
            if ('DataDiskNames' -in $vm.PSObject.Properties.Name -and @($vm.DataDiskNames).Count -gt 0) {
                Write-Verbose -Message 'Removing data disks...'
                foreach ($uri in $vm.StorageProfile.DataDisks.Vhd.Uri) {
                    $dataDiskStorageAcct = Get-AzStorageAccount -Name $uri.Split('/')[2].Split('.')[0]
                    $dataDiskStorageAcct | Remove-AzStorageBlob -Container $uri.Split('/')[-2] -Blob $uri.Split('/')[-1]
                }
            }
            Else {
                foreach ($disk in $vm.StorageProfile.DataDisks) {
                    Remove-AzDisk -DiskName $Disk.name -ResourceGroupName $vm.ResourceGroupName -Force
                }
            }



        }
            
        if (!$AsJob) {
            & $scriptBlock -VMName $VMName -ResourceGroupName $ResourceGroupName
        }
        else {
            $initScript = {
                $null = Login-AzAccount -Credential $Credential
            }
            $jobParams = @{
                'ScriptBlock'          = $scriptBlock
                'InitializationScript' = $initScript
                'ArgumentList'         = @($VMName, $ResourceGroupName)
                'Name'                 = "Azure VM $VMName Removal"
            }
            Start-Job @jobParams 
        }
    }
}