Azure — Windows Update Management for on-premises VMware VMs with snapshots

John Gakhokidze
3 min readFeb 22, 2022


All code is on github.

If part of your infrastructure is in Azure, and you have on premises servers which are logically bound to Azure, probably, it makes sense to manage updates from one place: Azure Automation — Update Management.

You can use Update Management in Azure Automation to manage operating system updates for your Windows and Linux virtual machines in Azure, physical or VMs in on-premises environments, and in other cloud environments. You can quickly assess the status of available updates and manage the process of installing required updates for your machines reporting to Update Management.

On premises infrastructure is not necessary to be registered in Azure Arc, instead one can install Microsoft Monitoring agent and point to correct Log Analytics Workspace.

My scenario: Manage VMware VMs Windows updates, but taking VMware snapshots before any Windows Updates.

There are several possible scenarios:

  • Implement webhook in pre-update Runbook to publicly faced server, and webhook will trigger snapshots
  • Implement Runbook to grub list of servers to be updated and put on blob, from on premises one can access blob using either scheduled job, or manually triggered.
  • Initiate script manually with KQL query similar to one when we are defining computer groups either by sever name, OS version etc — in one the deployments we will use this approach

Update table has many fields, which can be used — in the example below , I will use Product and Computer

Code is also in github:

| where (Product contains “Windows Server 2012 R2”) and (Computer contains “SOME_NAMING_SCHEMA” )
| distinct Computer

Be sure to run simple query in Query Editor as Update to get all possible fields

Now VMware part:

We will need VMware Power CLI and Az.Modules (Az.Accounts and Az.OperationalInsights) installed from where you call the script.

Quick go though script -check github for usable code.

# Set Powershell to system proxy, if you need, or comment next 3 lines
$Wcl = new-object System.Net.WebClient
$Wcl.Headers.Add(“user-agent”, “PowerShell Script”)
$Wcl.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials

# Connect to Azure

# Variables
$WorkspaceName = ‘WORKSPACE_NAME’

# Set Subscription where you Automation Account is located
Select-AZSubscription $subscription

# Get Workspace object
$Workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName $ResourceGroupName -Name $WorkspaceName

# Invoke KQL query
$QueryResults = Invoke-AzOperationalInsightsQuery -Workspace $Workspace -Query “Update| where (Product contains ‘Windows Server 2019’) and (Computer contains ‘SOME_NAMING_SCHEMA’)|distinct Computer”

# Note: KQL query returns FQDN name of server, depending on your VMware naming convention, you may want to trim
# In the example below, I am removing

$context=($QueryResults.Results|findstr -v Computer|findstr -v “\-\-\-”).Trim(“”)

#You can use -Credentials here, or just leave only user and will be authenticated
Connect-VIServer -Server $vcenter -User $user -Password ‘SOME_PASSWORD’

foreach($server in $context){
$name=”Pre Windows updates”
$vm = get-vm -name $server
write-host “creating snapshot $name for $”
# Running snapshot in sync, you may want to change to -runasync:$true
$snap = New-Snapshot -vm $vm -name $name -confirm:$false -runasync:$false

Once snapshots are ready schedule your update deployment

What about to remove snapshots?

Replace foreach block with code below :)

foreach ($server in $servers){
$vm = get-vm -name $server
$snap = get-Snapshot -vm $vm -name $name
write-host “removing snapshot $ for $”
# Removing snapshots in sync, you may want to change to -runasync:$true
remove-snapshot -snapshot $snap -confirm:$false -runasync:$false

In this article, I provided example how to integrated Azure Automation Updates Management with on premises VMware infrastructure.