Public/Reset-SCOMInstanceHealth.ps1

Function Reset-SCOMInstanceHealth {
  <#
  .SYNOPSIS
  Author: Tyson Paul
  Blog: https://monitoringguys.com/
  Version History:
  2023.03.03.1230 - Added $HideOutput, error handling, message output.
  2023.02.28.1111 - v1
 
  .LINK
  Criteria syntax: https://learn.microsoft.com/en-us/previous-versions/system-center/developer/bb437603(v=msdn.10)?redirectedfrom=MSDN
 
  .DESCRIPTION
     Will reset the health state for the designated objects.
 
  .EXAMPLE
  The command below will reset health for only the monitor related to each alert. The Alert IDs are piped to the function.
 
  PS C:\> Get-SCOMAlert -Criteria "ResolutionState <> 255 AND MonitoringObjectName LIKE '%https://www.harveywoodworking.com%'" | Select-Object Id | Reset-SCOMInstanceHealth
 
  .EXAMPLE
  The command below will reset health for only the monitor related to each alert.
 
  PS C:\> $Alerts = Get-SCOMAlert -Criteria "ResolutionState <> 255 AND MonitoringObjectName LIKE '%OneDriveForBusiness%'"
  PS C:\> Reset-SCOMInstanceHealth -AlertId $Alerts.Id -Verbose
 
  .EXAMPLE
  The command below will reset health for all active monitors of the related objects.
 
  PS C:\> $Alerts = Get-SCOMAlert -Criteria "ResolutionState <> 255 AND MonitoringObjectName LIKE '%OneDriveForBusiness%'"
  PS C:\> Reset-SCOMInstanceHealth -AlertId $Alerts.Id -AllMonitors -Verbose
 
  .OUTPUTS
     Task results
 
  #>


  [CmdletBinding()]
  Param (

    # Id/Guid of an alert object
    [Parameter(Mandatory=$false,
              ValueFromPipeline=$true,
              ValueFromPipelineByPropertyName=$true,
              Position=0,
              ParameterSetName='Parameter Set 1')]
    [ValidateNotNullOrEmpty()]
    [System.Object[]]$AlertId,

    [Parameter(Mandatory=$false,
              ParameterSetName='Parameter Set 1')]
    [switch]$AllMonitors,


    # Id/Guid of a monitoring object
    [Parameter(Mandatory=$false,
              ValueFromPipeline=$false,
              ValueFromPipelineByPropertyName=$false,
              Position=0,
              ParameterSetName='Parameter Set 2')]
    [ValidateNotNullOrEmpty()]
    [Alias("InstanceId")]
    [System.Object[]]$MonitoringObjectId,

    [string]$HideOutput = "false"
  )


  Begin {
    If (-NOT (Get-Module OperationsManager)) {
      . Import-SCOMPowerShellModule
    }
    [bool]$HideOutput = [System.Convert]::ToBoolean($HideOutput)
  }

  Process {
    # Process by AlertID
    If ($AlertId.Count) {
      $AlertId = $AlertId | Select-Object -Unique
      [array]$Alerts = Get-SCOMAlert -Id $AlertId
      If ($AllMonitors) {
        Reset-SCOMInstanceHealth -MonitoringObjectId ($Alerts.MonitoringObjectId)
      }
      Else {
        # ForEach blocks will only execute if at least one object exists.
        ForEach($Alert in $Alerts) {
          $Monitors = Get-SCOMMonitor -Id $Alert.MonitoringRuleId
          ForEach ($tmpMon in $Monitors) {
            $Instance = Get-SCOMClassInstance -Id $Alert.MonitoringObjectId
            ForEach ($I in $Instance) {
              # RESET
              Try {
                $ResetResult = $I.ResetMonitoringState($tmpMon)
                $msg = @"
RESET STATE:
TaskId: $($ResetResult.TaskId)
TaskResult: $($ResetResult.Status)
TaskOutput: $($ResetResult.Output)
Reset MonitorName: $($tmpMon.Name)
Monitor DisplayName: $($tmpMon.DisplayName)
Monitor Id: $($tmpMon.Id.Guid)
ObjectName: $($I.Name)
ObjectId: $($I.Id.Guid)
"@

                Write-Verbose $msg
                If (-NOT $HideOutput) {Write-Output $msg}
              } Catch {
                $_
              }

              # RECALC
              Try {
                $RecalcResult = $I.RecalculateMonitoringState($tmpMon)
                $msg = @"
RECALCULATE:
TaskId: $($RecalcResult.TaskId)
TaskResult: $($RecalcResult.Status)
TaskOutput: $($RecalcResult.Output)
Recalc MonitorName: $($tmpMon.Name)
Monitor DisplayName: $($tmpMon.DisplayName)
Monitor Id: $($tmpMon.Id.Guid)
ObjectName: $($I.Name)
ObjectId: $($I.Id.Guid)
"@

                Write-Verbose $msg
                If (-NOT $HideOutput) {Write-Output $msg}
              } Catch {
                $_
              }

            }
          }
        }
      }
    }

    # Process by Instance
    ElseIf ($MonitoringObjectId.Count) {
      ForEach ($MonId in ($MonitoringObjectId | Select-Object -Unique)) {
        $MonitoringObject = Get-SCOMClassInstance -Id $MonId
        If ($MonitoringObject) {
          $AllMons = (Get-SCOMMonitor -Instance $MonitoringObject -Recurse)

          <#
              # Reset unhealthy NON unit monitors
              $MonitorInstances = New-Object "System.Collections.Generic.List[Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitor]"
              $AllMons | Where-Object {$_.XMLTag -ne 'UnitMonitor'} | % {$MonitorInstances.Add($_) }
              $AllStates = $Instance.GetMonitoringStates($MonitorInstances)
              $UnhealthyStates = $AllStates | Where-Object {$_.HealthState -match 'Error|Warning'}
              ForEach ($State in $UnhealthyStates) {
              $tmpMon = Get-SCOMMonitor -Id $State.MonitorId
              $MonitoringObject.ResetMonitoringState($tmpMon)
              $MonitoringObject.ResetMonitoringState()
              }
          #>


          # Reset unhealthy UNIT monitors
          $MonitorInstances = New-Object "System.Collections.Generic.List[Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitor]"
          $AllMons | Where-Object {$_.XMLTag -eq 'UnitMonitor'} | % {$MonitorInstances.Add($_) }
          $AllStates = $MonitoringObject.GetMonitoringStates($MonitorInstances)
          $UnhealthyStates = $AllStates | Where-Object {$_.HealthState -match 'Error|Warning'}
          ForEach ($State in $UnhealthyStates) {
            $tmpMon = Get-SCOMMonitor -Id $State.MonitorId
            # RESET
            Try {
              $ResetResult = $MonitoringObject.ResetMonitoringState($tmpMon)
              $msg = @"
RESET STATE:
TaskId: $($ResetResult.TaskId)
TaskResult: $($ResetResult.Status)
TaskOutput: $($ResetResult.Output)
Reset MonitorName: $($tmpMon.Name)
Monitor DisplayName: $($tmpMon.DisplayName)
Monitor Id: $($tmpMon.Id.Guid)
ObjectName: $($MonitoringObject.Name)
ObjectId: $($MonitoringObject.Id.Guid)
"@

              Write-Verbose $msg
              If (-NOT $HideOutput) {Write-Output $msg}
            } Catch {
              $_
            }

            # RECALC
            Try {
              $RecalcResult = $MonitoringObject.RecalculateMonitoringState($tmpMon)
              $msg = @"
RECALCULATE:
TaskId: $($RecalcResult.TaskId)
TaskResult: $($RecalcResult.Status)
TaskOutput: $($RecalcResult.Output)
Recalc MonitorName: $($tmpMon.Name)
Monitor DisplayName: $($tmpMon.DisplayName)
Monitor Id: $($tmpMon.Id.Guid)
ObjectName: $($MonitoringObject.Name)
ObjectId: $($MonitoringObject.Id.Guid)
"@

              Write-Verbose $msg
              If (-NOT $HideOutput) {Write-Output $msg}
            } Catch {
              $_
            }
          }
        }
      }
    }#End ElsIf

  }#End Process

  End {}

}