If you are using Update Management to handle patching of Windows VMs in Azure, you are bound to see devices display in the “Not Assessed” compliance state from time to time. To remedy this, one can restart the service “Microsoft Monitoring Agent (HealthService).” This service has a corresponding process as well, and I check the start time of the service to ensure it actually restarted. There are many ways one can go about restarting a service, but I opted for a PowerShell script so I can have a report of the information on the corresponding process as well.
Just take a look at that beautifully crafted output. Device names have been intentionally hidden.
Provide a list of devices in the parent folder, and the targeted Service Name in the respective location, and this script will restart the service, and report the Name, Service, Status, and StartType in an array, so you can validate that everything went smoothly.
# Script written by Payton Flint
# See https://paytonflint.com/scripted-restart-of-service-azure-update-management/
# Set target Service Name
$ServiceName = "HealthService"
# Identify location of script
$ScriptPath = Split-Path ($MyInvocation.MyCommand.Path) -Parent
# Set systems list location
$AllSystems = Get-Content "$ScriptPath\DeviceList.txt"
workflow RestartService {
Param (
[string[]]$ServiceName,
[string[]]$ScriptPath,
[string[]]$AllSystems,
[string[]]$ItemArray
)
Foreach -Parallel ($system in $AllSystems) {
inlinescript {
# Create array
$ItemArray= @()
#Get service object
$ServiceObj = Get-Service -ComputerName $Using:system -Name $Using:ServiceName
# Gather info on target service for report array
$ServiceDisplayName = $ServiceObj | Select-Object -ExpandProperty DisplayName
$ServiceStatus = $ServiceObj | Select-Object -ExpandProperty Status
$ServiceStartType = $ServiceObj | Select-Object -ExpandProperty StartType
# Restart target service
Write-Output "Restarting $ServiceDisplayName service on $Using:system"
Restart-Service -InputObject $ServiceObj -Force -Verbose
Write-Output ""
# Identify process ID by name
$ProcessID= Get-Process -ComputerName $Using:system -Name $Using:ServiceName | Select-Object -ExpandProperty ID
# WMI query on targeted win32_process by ID
$ProcessWMI = Get-WmiObject Win32_Process -ComputerName $Using:system -Filter "ProcessID='$ProcessID'"
# Convert creation date to date+time
$CreationDate = $ProcessWMI.ConvertToDateTime($ProcessWMI.CreationDate)
# Append items to array
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "Name" -Value $($Using:system)
$obj | Add-Member -MemberType NoteProperty -Name "ServiceName" -Value $($Using:ServiceName)
$obj | Add-Member -MemberType NoteProperty -Name "ServiceDisplayName" -Value $($ServiceDisplayName)
$obj | Add-Member -MemberType NoteProperty -Name "Status" -Value $($ServiceStatus)
$obj | Add-Member -MemberType NoteProperty -Name "StartType" -Value $($ServiceStartType)
$obj | Add-Member -MemberType NoteProperty -Name "ProcessID" -Value $($ProcessID)
$obj | Add-Member -MemberType NoteProperty -Name "ProcessStartTime" -Value $($CreationDate)
$ItemArray += $obj
# Display array
Write-Output $ItemArray
# Clear/reset array
$ItemArray = $null
}
}
}
RestartService -ServiceName $ServiceName -ScriptPath $ScriptPath -AllSystems $AllSystems