Azure Update Management: Log Analytics Agents & Automation Accounts


Many of our customers would like to start patching servers as soon as possible using a single Update Management Solution deployed on a single Log Analytics Workspace. To achieve this goal you need to deploy the Agent (newer version) or the Microsoft Monitoring Agent (current version) on machines that could be domain joined or even on a workgroup. To add even more complexity, the use of PowerShell could be restricted.  

The above requirements can be broken up into 2 scenarios:


  • [Scenario 1] – Virtual Machine on Azure that is already connected to the domain. It might or might not have the agent. It might or might not have the proxy settings filled in.
  • [Scenario 2] – on Azure that is not connected to the domain. It might or might not have the agent or proxy settings filled in.

We will now explore 3 Options for deploying the agents and 3 Query Methods to confirm if the installation was actually successful.

The 3 Options for deploying the Agent

Option 1 – Azure Policy

For both Scenario 1 and Scenario 2 this can be used. We would choose the Enable for VMs Policy Initiative.


It can be assigned to any Management Group or Subscription


  1. Simply choose your Log Analytics Workspace that is connected to the Account Containing Update Management


I normally also create a Remediation Managed Identity


  1. Set a default Non-Compliance message


  1. And create


If we immediately go to the Deploy-VM-Monitoring we can view the compliance


By clicking on Non-Compliant Resources I can see the machines


But this policy might not have the Failed/Succeeded metric for the actual extension. For that we can use 3 query methods: Azure Resource Graph Explorer, Azure CLI Bash, Azure Cloud Shell PowerShell.

Option 2 – PowerShell

For Scenario 1 and Scenario 2 Our official method to deploy the Log Analytics Extension with PowerShell in Azure can be seen below.

$PublicSettings = @{"workspaceId" = "myWorkspaceId"}
$ProtectedSettings = @{"workspaceKey" = "myWorkspaceKey"}
Set-AzVMExtension -ExtensionName "MicrosoftMonitoringAgent" `
    -ResourceGroupName "myResourceGroup" `
    -VMName "myVM" `
    -Publisher "Microsoft.EnterpriseCloud.Monitoring" `
    -ExtensionType "MicrosoftMonitoringAgent" `
    -TypeHandlerVersion 1.0 `
    -Settings $PublicSettings `
    -ProtectedSettings $ProtectedSettings `
    -Location WestUS

Or if you are using the Agent

Set-AzVMExtension -ExtensionName "AMAWindows" `
    -ExtensionType AzureMonitorWindowsAgent `
    -Publisher " Microsoft.Azure.Monitor" `
    -ResourceGroupName "myResourceGroup" `
    -VMName "myVM" `
    -TypeHandlerVersion 1.0 `
    -Location WestUS

If the Extension already Exists, you mentioned there needs to be some proxy settings filled in.

One way to configure Proxy settings quickly on multiple machines would be to use the Custom Script Extension. PowerShell 7 brings the functionality “-Parallel” which will run multiple instances of the same script.

To manually run the Customer Script Extension Proxy Setting on a Server and set the correct Workspace we can use the below script

#This section adds a new Workspace
$workspaceId = ""
$workspaceKey = ""

$mma = New-Object -ComObject 'AgentConfigManager.MgmtSvcCfg'
$mma.AddCloudWorkspace($workspaceId, $workspaceKey)

#This section is where the Proxy can be configured
$proxyMethod = $mma | Get-Member -Name 'SetProxyUrl'
if (!$proxyMethod)
    Write-Output 'Health Service proxy API not present, will not update settings.'
#Clears Proxy settings in MMA
Write-Output "Clearing proxy settings."

#Adds new proxy settings
Write-Output "Setting proxy to $ProxyDomainName"


If we wanted to Automate this for multiple machines, we could do something like mentioned in the following article.

How to run scripts against multiple Azure VMs by using Run Command – Thomas Maurer

Option 3 – Desired State Configuration

is another great way of ensuring the MMA is present on machines and configured correctly. This also makes execution easier because you can use a specified approved account or Hybrid runbook worker to execute the DSC in case of strict security rules where only certain accounts can run PowerShell .


  1. Download the MMA Agent


  1. Extract the contents because we want the MSI


  1. Open Notepad and save the below as “Get-MSIFileInformation.ps1” in your Downloads folder.
try {
    $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
    $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($Path.FullName,0))
    $Query = "SELECT Value FROM Property WHERE Property = '$($Property)'"
    $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query))
    $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
    $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null)
    $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1)
    return $Value
catch {
    Write-Output $_.Exception.Message
  1. Open PowerShell and cd to Downloads, and run the Newly saved MSI Script
.Get-MSIFileInformation.ps1 -Path C:UsersDownloadsMMASetup-A
MD64MOMAgent.msi -Property ProductCode


  1. Create Variables for

OPSINSIGHTS_WS_ID  (This is your Workspace you need the server to connect to),

OPSINSIGHTS_WS_KEY (This is the key for the workspace),

OPINSIGHTS_PROXY_URL (This is the proxy URL in format


  1. Import the Module into the Account



  1. Save the below script as MMAgent.ps1 and Modify the ProductID that was found in Step 4. Also update the ProductID as found in Step 4.
Configuration MMAgent
    $OIPackageLocalPath = "C:DeployMMASetup-AMD64.exe"
    $OPSINSIGHTS_WS_ID = Get-AutomationVariable -Name "OPSINSIGHTS_WS_ID"
    $OPSINSIGHTS_WS_KEY = Get-AutomationVariable -Name "OPSINSIGHTS_WS_KEY"
    $OPINSIGHTS_PROXY_URL = Get-AutomationVariable -Name " OPINSIGHTS_PROXY_URL"

    Import-DscResource -ModuleName xPSDesiredStateConfiguration
    Import-DscResource -ModuleName PSDesiredStateConfiguration

    Node OMSnode {
        Service OIService
            Name = "HealthService"
            State = "Running"
            DependsOn = "[Package]OI"
        xRemoteFile OIPackage {
            Uri = ""
            DestinationPath = $OIPackageLocalPath
        Package OI {
            Ensure = "Present"
            Path  = $OIPackageLocalPath
            Name = "Microsoft Monitoring Agent"
            ProductId = "88EE688B-31C6-4B90-90DF-FBB345223F94"
            DependsOn = "[xRemoteFile]OIPackage"
  1. Import the MMAgent.ps1 script into the Automation Account State Configuration under Configurations. After the import click on MMAgent and click Compile.



  1. Assign a computer or node and within a few minutes the Agent will get pushed to the machine.




The 3 Methods to Query Agent Installation

1 Azure Resource Graph Explorer [Query All Servers]*

// LogAnalyticsandHealthyAgentv5
// All Running, All Health and All Monitoring Extensions
// Click the "Run query" command above to execute the query and see results.
// Linux and Windows Agents
// Click the "Run query" command above to execute the query and see results.
// This query will show machines that are currently running.
// This query will show the extensions that relates to MicrosoftMonitoringAgent','AzureMonitorWindowsAgent'and 'OMSAgentForLinux'

| where type == 'microsoft.compute/virtualmachines'
| where properties.extended.instanceView.powerState.displayStatus=="VM running" and properties.osProfile.windowsConfiguration.provisionVMAgent=="true" or properties.extended.instanceView.powerState.displayStatus=="VM running" and properties.osProfile.linuxConfiguration.provisionVMAgent=="true"
| extend
    JoinID = toupper(id),
    OSName = tostring(name),
    OSType = tostring(properties.storageProfile.osDisk.osType),
    RSG = tostring(resourceGroup),
    SUB = tostring(subscriptionId),
    LOC = tostring(location)
| join kind=leftouter(
| where type == 'microsoft.compute/virtualmachines/extensions' and name == 'MicrosoftMonitoringAgent' or name == 'AzureMonitorWindowsAgent' or name == 'OMSAgentForLinux'
// | where properties.provisioningState == 'Succeeded'
  VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
  props = tostring(properties.settings),
  prvstatus = tostring(properties)
)on $left.JoinID == $right.VMId
| summarize Extensions = make_list(props) by id, OSName, OSType, RSG, SUB, LOC, prvstatus

Example of execution. This will show me all machines that are running and their provisionState of the Extension that related to Log Analytics.

The subscription where the policies have not applied yet.


Another subscription to showcase the Provisioning Status


[box type=”info”] * Although Resource Graph is the easiest way to get information about all machines at once it takes longer to update than the Bash or PowerShell. This means if you are querying your machines and you see one has failed and you repair the failure Resource Graph will take time to update. Therefore if you want realtime information please refer to Azure CLI or Cloud Shell, the limitation being only looking at one server.[/box]

2 Azure CLI Bash [Deep Dive 1 Server Real Time]

If I find that I need to deep dive into one specific server to see if the Extension Provisioning succeeded or failed I can use Cloud Shell Bash in the Azure Portal.

The command is:

az vm extension show -g  --vm-name  --name MicrosoftMonitoringAgent


3 Azure Cloud Shell PowerShell [Deep Dive 1 Server]

The Bash is great at showing a one-pager but if I wanted to dive into even more detail about why an extension failed I can use Cloud Shell PowerShell

The command is:

Get-AzVM -ResourceGroupName  -Name  -Status

I can look at the Extensions Portion and I will have the error code and message


And the ExtensionHandlers will give me some more information


These are the only methods to assist you in querying your VM Extensions. We need them to be healthy to connect to the Automation Account.

Thank you for reading and I hope this has been beneficial to you in your patching journey.

Some more helpful Links


This article was originally published by Microsoft's Core Infrastructure and Security Blog. You can find the original article here.