Search code examples
powershellazureazure-virtual-machineazure-automation

Monitoring Services on an Azure VM using an Azure Runbook


I have a Powershell script that enumerates running services and their current state using Get-WmiObject Win32_Service. Initial version based on this one and then modified for Azure. When I run the script in Powershell (without the azure automation parts) on my location machine it works fine and I can connect to all the machines of interest, but when I port it to a runbook i get the following error: "Get-WmiObject : The RPC server is unavailable."

Q: Is the problem with permissions for the automation account? If so, what account should I add to the local machines to resolve the issue?

Q: Is Get-WmiObject not a valid way to initiate the connection? If not, what should I try instead?

The code I'm using is below:

[CmdletBinding(SupportsShouldProcess = $true)]
param(

    # Servers to check
    [Parameter(Mandatory=$true)][string[]]$ServerList,

    # Services to check for
    [Parameter(Mandatory=$true)][string[]]$includeService
    ) 

# Following modifies the Write-Verbose behavior to turn the messages on globally for this session
$VerbosePreference = "Continue"

$connectionName = "AzureRunAsConnection"

# retry
$retry = 6
$syncOk = $false

$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName 
do
{ 
    try
    {  
        Add-AzureRmAccount -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId $servicePrincipalConnection.ApplicationId -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
        $syncOk = $true
    }
    catch
    {
        $ErrorMessage = $_.Exception.Message
        $StackTrace = $_.Exception.StackTrace
        Write-Warning "Error during sync: $ErrorMessage, stack: $StackTrace. Retry attempts left: $retry"
        $retry = $retry - 1       
        Start-Sleep -s 60        
    }
} while (-not $syncOk -and $retry -ge 0)

Select-AzureRMSubscription -SubscriptionId $SubscriptionId -TenantId $servicePrincipalConnection.TenantId
$currentSubscription = Get-AzureRMSubscription -SubscriptionId $SubscriptionId -TenantId $servicePrincipalConnection.TenantId
Set-AzureRmContext -SubscriptionId $SubscriptionId;

$props=@()

[System.Collections.ArrayList]$unreachableServers = @()

Foreach($ServerName in ($ServerList)) 
{  
    try
    {
        $service = Get-WmiObject Win32_Service -ComputerName $servername
    }
    catch
    {}

    if ($Service -ne $NULL)  
    {  
        foreach ($item in $service)  
        {  
             #$item.DisplayName  
            Foreach($include in $includeService)   
            {                         
                     #write-host $include                                      
                if(($item.name).Contains($include) -eq $TRUE)  
                { 
                    $props += [pscustomobject]@{
                    servername = $ServerName
                    name =  $item.name
                    Status = $item.Status 
                    startmode = $item.startmode 
                    state = $item.state
                    serviceaccount=$item.startname
                    DisplayName =$item.displayname}
                }  
            }  
        }  
    } 
    else
    {
        Write-host "Failed to contact server: "$ServerName
        $unreachableServers.Add($ServerName)
    } 
}  

$props | Format-Table Servername,Name,startmode,state,serviceaccount,displayname  -AutoSize

Solution

  • I am assuming that you are using the Azure Automation Hybrid Worker functionality. Be default it runs under the System account. However you can use a different account to run the runbook under. This is documented here: Azure Automation Hybrid Worker; Look under the RunAs account section. Use the same account that works when you try it directly.