Azure Virtual Desktop Image Management Automated – Part 4 AVD Clean up unused resources

  • last updated: Mon, 12 Sep 2022 07:07:30

The current situation, we have created new disks, snapshots, virtual machines, networks, images and session hosts. All the resources has been added to the existing AVD hostpool. Now it is time to cleanup the old resources, to keep everything nice and clean. In this part we will take care of removing components related to the old image version.

This post is a part of the series Azure Virtual Desktop Image Management Automated.

  1. Create AVD image version based on existing config with PowerShell – Part 1
  2. Save AVD image with Sysprep as Image Gallery version – Part 2
  3. Create AVD Sessionhosts based on Shared Image Gallery version – Part 3
  4. AVD housekeeping, removing all unused sessionhosts, disks and images – Part 4
  5. Monitor Image Versions with Azure Monitor – Part 5
  6. Enroll MSIX packages automated – Part 6 – (coming soon)

Tags, tags, tags

After deploying the entire environment you have created a new disk, a snapshot, Azure virtual machines, network interfaces, an image and session hosts. This a quite a lot of resources and you will need to do a good job keeping all these resources up-to-date. Well, there is a better housekeeping solution.
I work a lot with tags. By tagging resources consequent you can find the relationship between resources by just one single click on a tag.

Let’s say you have the Azure VM resources with the ImageVersion. By clicking the tag you will get every resources which is in relation with that specific ImageVersion.

virtual machine By clicking the tag you will see the related disks, virtual machines, network interfaces and other resources with this tag value.

virtualmachine-resources Now we know how to get all the related resources based on a tag lets fill the automation part.

Get the resources

In the Azure portal you can click the tag you need and do your job (per tag). Because PowerShell doesn’t know the latest version, we need to find the latest images version used in the AVD hostpool.

AVD Hostpool

By knowing the AVD hostpool every other component can be find due some reverse engineering.

    [parameter(mandatory = $true, ValueFromPipelineByPropertyName)]$hostpoolName,
    [parameter(mandatory = $true, ValueFromPipelineByPropertyName)]$deleteResources

import-module az.desktopvirtualization
import-module az.compute

# Getting the hostpool first
$hostpool = Get-AzWvdHostPool | ? { $_.Name -eq $hostpoolname } 
if ($null -eq $hostpool){
    "Hostpool $hostpoolname not found"
# Creating VM configuration based on existing VM's in specific hostpool, selecting first one
$hostpoolRg = ($hostpool).id.split("/")[4]
Write-Output "Hostpool resourcegroup is $hostpoolRg"

To get the Shared Image Gallery information we need to know the sessionhost first. Sessionhost (actually an Azure VM) information contains storage information where the image information is stored.

# Get one of the current production VM's for getting the share image gallery info
$sessionHosts = Get-AzWvdSessionHost -ResourceGroupName $hostpoolRg -HostPoolName $
$existingSessionHost = ($sessionHosts.Name.Split("/")[-1]).Split(".")[0]
$productionVm = Get-AzVM -Name $existingSessionHost

version The next part will use the Azure VM information to get the Shared Image Gallery information and will search for the oldest version. By sorting on published date and grabbing the first result you will get the oldest version.

# Source:
# Creating image version based on the image created few steps ago
$imageReference = ((get-azvm -Name $productionVm[-1].name -ResourceGroupName $productionVm[-1].ResourceGroupName).storageprofile.ImageReference).id
$galleryImageDefintion = get-AzGalleryImageDefinition -ResourceId $imageReference
$galleryName = $imageReference.Split("/")[-3]
$gallery = Get-AzGallery -Name $galleryName
$versions = Get-AzGalleryImageVersion -ResourceGroupName $gallery.ResourceGroupName -GalleryName $gallery.Name -GalleryImageDefinitionName $galleryImageDefintion.Name
$oldestVersion = $($versions | Sort-Object PublishedDate).name[0]
"Found version $oldestVersion"


Knowing the oldest version we can search for any resource with the ImageVersion Tag where the value has the oldest version in it.
If the parameter $deleteResources is $true the resources will be deleted. Else the WhatIf will be used.

$tag = @{ImageVersion = $oldestVersion}
foreach ($resource in (Get-AzResource -Tag $tag)) {
    if ($deleteResources) {
        Remove-AzResource -ResourceId $resource.ResourceId -Force
        Remove-AzResource -ResourceId $resource.ResourceId -WhatIf

What if you don’t use tags

Every resource related to tag ImageVersion has been deleted. I can imagine you don’t use tags at this moment. Don’t worry, there is a way to remove resources without the use of tags. In the foreach loop the script searches for a specific tag. If you don’t use tags this way searching for them is quite difficult :), so we need to find an another way.
There is a way by searching Azure virtual machines on a specific storage profile. The ImageReference object contains an image version which can be used. By filtering that object you will get virtual machine only. By using the objects in the virtual machine you can find

foreach ($resource in (get-azvm | ? {$_.storageprofile.ImageReference.ExactVersion -eq $oldestVersion})) {
    if ($deleteResources) {
        Remove-AzResource -ResourceId $resource.ResourceId -Force
        Remove-AzResource -ResourceId $resource.ResourceId -WhatIf

Good luck and take care. This script will **DELETE **resources, i’m not responsible for any accidentally delete.

Thank you for reading my blog azure virtual desktop image management automated – part 4 avd clean up unused resources.
I hope you got a bit inspired. Enjoy your day and happy automating 👋

comments powered by Disqus

Related Posts

Monitor active M365 ServiceHealth services only with PowerShell

You have some Microsoft 365 (M365) customers which you like to monitor. Every day you are looking at the customer specific M365 portal looking for Microsoft event.

Read more

How to use REST API with Powershell

The past few years REST API became important more and more. REST API is a common way for communicating against and between applications. Azure and Microsoft 365 also using REST API’s.

Read more

Azure Virtual Desktop Image Management Automated - Part 2 Save AVD image with Sysprep as Image Gallery version

This is part two of a serie posts about AVD disk management. In this blogpost I will explain how to finish a disk with sysprep and deploy it as a version into the Azure Shared Image Gallery automated.

Read more