Find Azure VMs that are "Shut Down" but not "Deallocated"

As you likely know, if you shut down an azure VM from the operating system, Azure does not deallocate resources to that VM, and therefor you are still being charged for those resources. In order to get the VM to stop billing, it has to be in the 'deallocated' state. In order to deallocate, Azure must be used to shut down the VM, not the OS (you can use the portal, CLI or PowerShell). Below is a powershell script to find virtual machines that are shut down but not deallocated, check to see if it has a static IP (VMs release their IP when deallocated) and if it does not have a static public or private IP, deallocate the VM. GitHub link is HERE #Login-AzureRmAccount $rg = get-azurermresourcegroup foreach ($r in $rg){ $vm = Get-AzureRmVM -ResourceGroupName $r.resourcegroupname -Status | Where-Object {$_.powerstate -like 'VM stopped'} foreach ($v in $VM) {$nic = $v.NetworkProfile.NetworkInterfaces $string = $nic.id.ToString() $nicname = $string.split("/")[-1] $ipconfig = Get-AzureRmNetworkInterface -ResourceGroupName $r.ResourceGroupName -Name $nicname $pip = $ipconfig.IpConfigurations.publicipaddress.Id if ($pip -ne $null) {$pipname = $pip.split("/")[-1] $pip = Get-AzureRmPublicIpAddress -Name $pipname -ResourceGroupName $r.ResourceGroupName $pip = $pip.PublicIpAllocationMethod} if (($ipconfig.IpConfigurations.privateIPAllocationMethod -like "Static") -and ($pip -ne 'Dynamic' -or $pip -eq $null)) {stop-azurermvm -resourcegroupname $r.ResourceGroupName -Name $v.name -Force write-output "Stopping VM" $v.name} Else {write-output $v.name "Has Dynamic IP and Can't be deallocated without releasing the IP. Please use the portal to shutdown after confirming that releasing the IP is OK"} } }