SCOM Maintenance Mode PowerShell

My thanks to Matt Taylor and Kevin Holman, Ralph Kyttle, and John Kavanagh for their guidance!

Updated 22 Feb 2019



Read on if these apply
Trying to start, update, or end SCOM MM

Get alerts when MM is updated
PowerShell only in your shop!
SCORCH in play but need to convert runbooks to straight PowerShell

Ran into issues using Set-SCOMMaintenanceMode, as the cmdlet doesn't put ALL the recursive classes under Windows Computer




Set-SCOMMaintenanceMode cmdlet is actually “by design.”  ☹


Start-SCOMMaintenanceMode assumes you want recursive action when you start maintenance mode….

Pick a Windows Computer and it places the Windows Computer object (AND all contained objects) into MM.


Computer in MM

All contained objects in MM



However, the problem is that Set-SCOMMaintenancemode does not have an understanding of recursiveness.

Command changes the MM entry for the Windows Computer, but NOT all the contained objects.  So they retain the original setting.


Health explorer looks like this, resulting in unwanted alerts





NOTE these $Time and DateTime Method are dependent on the delay between running the commands
If you start MM, and wait 5 minutes, then update, the total MM duration will be ~20 minutes




Maintenance Mode options and examples

# Setup variables for MM

# Example 1 Windows Computer

$server = "Servername.FQDN"

$instance = (get-scomclass -DisplayName "Windows Computer" |Get-SCOMClassInstance | ? { $_.DisplayName -eq $server } )

# Set time for 6 minutes

$Time = (Get-Date).addMinutes(6)

Start-SCOMMaintenanceMode -Instance $Instance -EndTime $Time -Comment "Starting Maintenance Mode." -Reason "PlannedOther"


# Example 2

# Business needs require Windows Operating System monitoring to occur while Application is in maintenance

# My Example is Defender, could be SQL, MSMQ, Lync, Skype, or your custom class created for your application

$Class = (get-scomclass)
$Class | ? { $_.Name -like "*Defender*" } | fl DisplayName,Name
$Class | ? { $_.Name -like "*Defender*" } | fl DisplayName,Name

DisplayName : Protected Endpoint
Name        : Microsoft.WindowsDefender.ProtectedServer

DisplayName : Protected Candidate
Name        : Microsoft.WindowsDefender.ProtectedServerCandidate

DisplayName : Unprotected Endpoint
Name        : Microsoft.WindowsDefender.UnprotectedServer

DisplayName : Microsoft Windows Defender Class
Name        : Microsoft.Windows.Defender.Class

# Choose the class needed

$server = "Servername.FQDN"

$instance = ( $Class | ? { $_.Name -like "Microsoft.Windows.Defender*" } |Get-SCOMClassInstance | ? { $_.DisplayName -eq $server } )

# Verify Instance variable


PS C:\Users\scomadmin> $instance

HealthState     InMaintenanceMode  DisplayName
-----------     -----------------  -----------
Success               False


# Don't forget to add time variable

$Time = (Get-Date).addMinutes(6)

# Start maintenance mode

Start-SCOMMaintenanceMode -Instance $Instance -EndTime $Time -Comment "Starting Maintenance Mode." -Reason "PlannedOther"





Start, Update, End and Verify Maintenance mode syntax


# Start MM via PoSH cmdlet

Start-SCOMMaintenanceMode -Instance $Instance -EndTime $Time -Comment "Starting Maintenance Mode." -Reason "PlannedOther"



# Start MM using method vs. PowerShell cmdlet

Note Recursive in $WCobj.ScheduleMaintenanceMode

$windowsComment="Testing Maintenance Mode"

$server= ""
$instance = (get-scomclass -DisplayName "Windows Computer" |Get-SCOMClassInstance | ? { $_.DisplayName -eq $server } )
$instance.ScheduleMaintenanceMode([datetime]::Now.touniversaltime(),([datetime]::Now).addminutes($windowDuration).touniversaltime(), "$windowReason", "$windowsComment" , "Recursive")

# Drop Recursive if you don't want it (but can't imagine why you would!)



# Update MM

# Make sure you've put object in MM

$server= ""
$instance = (get-scomclass -DisplayName "Windows Computer" |Get-SCOMClassInstance | ? { $_.DisplayName -eq $server } )

# 15 minutes in the future
$instance.UpdateMaintenanceMode([System.datetime]::Now.touniversaltime().addminutes(15),[Microsoft.EnterpriseManagement.Monitoring.MaintenanceModeReason]::PlannedOther,[System.string]::"Adding 15 minutes to the end time.",[Microsoft.EnterpriseManagement.Common.TraversalDepth]::Recursive);


# Stop MM

# Make sure you've put object in MM

# Immediate

# The method does not allow future timeframes to StopMaintenance Mode



Verification steps


# Verify MM

get-scommaintenancemode -ComputerName $instance.Name|fl MonitoringObjectId,StartTime,ScheduledEndTime

NOTE This will error if you've stopped maintenance


PS C:\Users\scomadmin> get-scommaintenancemode -ComputerName $instance.Name
get-scommaintenancemode : The Data Access service is either not running or not yet initialized. Check the event log
for more information.
At line:1 char:1
+ get-scommaintenancemode -ComputerName $instance.Name
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (Microsoft.Syste...anceModeCommand:GetSCMaintenanceModeCommand) [Get-S
COMMaintenanceMode], ServiceNotRunningException
+ FullyQualifiedErrorId : ExecutionError,Microsoft.SystemCenter.OperationsManagerV10.Commands.GetSCMaintenanceMode



# Validate MM through Operations Manager Event ID’s 1215 and 1216 logged

get-eventlog -LogName "Operations Manager" | ? { $_.EventID -eq 1215 -OR $_.EventID -eq 1216 } |fl EventID,TimeGenerated,Message

# Alternate command to check latest 100 events

get-eventlog -LogName "Operations Manager" -newest 100 | ? { $_.EventID -eq 1215 -OR $_.EventID -eq 1216 } |fl EventID,TimeGenerated,Message



# Error if object NOT in MM

Cannot find an overload for "UpdateMaintenanceMode" and the argument count: "1".

At line:1 char:1

+ $WCobj.UpdateMaintenanceMode(([System.datetime]::Now).addminutes(15). ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodException

    + FullyQualifiedErrorId : MethodCountCouldNotFindBest


PS C:\Windows\system32>


Testing System datetime

PS C:\Windows\system32> [System.datetime]::Now.addminutes(15)


Thursday, August 24, 2017 9:18:04 AM



PS C:\Windows\system32> ([System.datetime]::Now.addminutes(15)).touniversaltime()


Thursday, August 24, 2017 2:18:16 PM






PowerShell cmdlets


Ralph Kyttle Blog

DateTime Methods

MaintenanceModeReason Method

StopMaintenanceMode Method

UpdateMaintenanceMode Method


MM deluxe custom script

Comments (6)

  1. Just because I have created elaborate processes… the problem with the start process is that it is not recursive and there will still be lots of false SCOM alerts, as where the stop you are using is recursive, There is a ScheduleMaintenanceMode method and like the Stop the documentation indicates it could be recursive but I can not get it to work for the life of me. I know this is an older post but just throwing it out there…

    1. kjustin1996 says:

      Hello John,
      What version and UR are you running?

      Are you targeting objects other than Windows Computer for maintenance mode?
      The Start-SCOMMaintenanceMode can be targeted at other classes than Windows Computer.
      If you are targeting other classes, the risk is correct – a class in maintenance mode may not contain the relevant sub-classes that need to be in maintenance mode (and alerts are generated).

      The best practice is to put the windows computer into maintenance, as nearly all classes roll up to that base level class (and thereby are put into maintenance).
      Groups is another alternative.
      Example – I created a custom Lync 2013 group with various classes, SQL servers, etc. so the Lync servers would go into maintenance and not alert the team during patching.

      SCOM 2016 PowerShell docs site

      1. SCOM 2012

        Yeah… a computer object can have a number of related objects, puttling the computer into maintenance mode with the CMDLet does not cover the related object, for example “Microsoft.MSMQ.6.3.Servers” so a server is gracefully rebooted but there might be an alert regarding to MSMQ services….

        I did get
        ScheduleMaintenanceMode([datetime]::Now.touniversaltime(),([datetime]::Now).addminutes($windowDuration).touniversaltime(), “$windowReason”, “$windowsComment” , “Recursive”)
        to work

      2. And admittedly the habit of using a extracted list and looping was “learned” as my first task was using modifygroupmembership.ps1 and creating an instance list suitable for that function set.
        I liked how the example above used the Method and I prefer that over a CMDLet, just personal preference. Part of my code was bad habits but I also had issues using the ScheduleMaintanceMode method.
        I do appreciate the feedback, always nice to see a different approach and makes the code better 🙂

  2. kjustin1996 says:

    Hey John,
    Updated the blog post with your example. Added some syntax for the method (tested what you provided, and noted you as a source at the top)

    As you mentioned the MSMQ class/object, added commands below to help someone find their class/instance.

Skip to main content