SCOM 2012 Maintenance Mode PowerShell Script Problems

I've seen other questions about this topic before, but none of them seem to address my specific problem, so I am starting a new thread.

I am writing a script to put a single server (not a group) into maintenance mode.   Here is the command that it ultimately tries to call:

 Start-SCOMMaintenanceMode-Instance$Instance-EndTime$EndTime-Reason$Reason-Comment$Comment     

So an exmaple would look like this:

Start-SCOMMaintenanceMode -Instance "$Instance -EndTime "02/03/2014 15:26:00" -Reason "PlannedOther" -Comment "Testing Maintenance Mode"

When my script tries to run this command, this is the error message that I get:

Start-SCOMMaintenanceMode : Start time must be before end time for maintenance mode.

Parameter name: startTime

At C:\users\x036036\Desktop\Start-SCOMMaintenanceModeForServer.ps1:143 char:21

+                     Start-SCOMMaintenanceMode -Instance $Instance -EndTime $EndT ...

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

    + CategoryInfo          : NotSpecified: (Microsoft.Syste...anceModeCommand:StartSCMaintenanceModeCommand) [Start-SCOMMaintenance

   Mode], ArgumentOutOfRangeException

    + FullyQualifiedErrorId : ExecutionError,Microsoft.SystemCenter.OperationsManagerV10.Commands.StartSCMaintenanceModeCommand

I've tried to look at Start-SCOMMaintenanceMode help online, but I don't see that "startTime" is a parameter.  So what is this error message talking about?  What am I missing?  

February 3rd, 2014 9:52pm

Hi

The Problem seems to be that the cmdlet does not recognize the end time correctly. There is no start time because as soon you fire the cmdlet this is your start time and end time is like "start time + 1h = end time".

Try this script...

Save this into a Set-MaintenanceMode.ps1 and run it like

Set-MaintenanceMode.ps1 "Server.domain.com" 1 "my comment"

param(
[Parameter(Position=1,mandatory=$true)][string]$computername,
[Parameter(Position=2,mandatory=$true)][int]$hours,
[Parameter(Position=3,mandatory=$true)][string]$comment
)

$error.clear()

import-module operationsmanager
$start = get-date
$end = $start.addhours($hours)
$class = Get-SCOMClass -name System.Computer
$mmobject = get-scommonitoringobject -Class $class | where{$_.displayname -eq $computername}

# Check if already in Maintenance Mode


if(!$mmobject)
 {
 $output = "The object was not found in SCOM"
 Write-Host $output -foregroundcolor yellow
 }

if($mmobject.inmaintenancemode -eq $true)
 {
 $output = "The object is already in maintenance mode"
 Write-Host $output -foregroundcolor yellow
 }

if($mmobject.inmaintenancemode -eq $false)
 {
 Start-SCOMMaintenanceMode -Instance $mmobject -EndTime $end -Comment $comment
 $output = "The object is now in maintenance mode"
 Write-Host $output -foregroundcolor yellow
 }

Note: For $class, you can pick any class which fits your needs, e.g. Microsoft.Windows.Computer etc.

Hope this helps,

Stefan

Free Windows Admin Tool Kit Click here and download it now
February 3rd, 2014 10:19pm

I haven't tried out your script just yet, but that is interesting.  My whole thing is that this actually ties into an existing webpage.  That webpage uses dates formatted like this:   2/4/2014 4:26:00 PM

Within my script I take that date in as the $EndTime parameter, in the format above, and simply convert it to a [datetime] like so:

$EndTime = [datetime]$EndTime

I added some lines to print the resulting $EndTime, and also a line to print what results from a Get-Date, which is what you used in your script above.  So this is what I added:

$NowTime = (GET-DATE)
Write-Verbose $NowTime
$EndTime = [datetime]$EndTime
Write-Verbose $EndTime

This is what prints out:
VERBOSE: 02/04/2014 08:41:40
VERBOSE: 02/04/2014 16:26:00

So those both appear to be in the same format to me.   So I'm still not sure what I am doing wrong...

 

But I'm going to try your script above and see how that works.

February 4th, 2014 3:00pm

OK, I did try out your script and it did in fact work.   I would still like to get my own to work since it has a little more stuff built into it.  Perhaps it makes the most sense for me to post my code, and see if you might be able to assist me.   So here's my code:

[CmdletBinding(SupportsShouldProcess=$true)]            
        param            
        (            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='What is the server you want to put in Maintenance Mode?')]            
        [Alias("Server")]            
        [string[]]$ServerName,            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$false,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. This is a required parameter. Format is 1/29/2014 8:59:26 AM')]            
        [Datetime]$EndTime,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='PlannedOther, UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity')]            
        [string]$Reason,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Allows you to type a comment about the maintenance activity.')]            
        [string]$Comment,            
        [switch]$EventLog            
        )            
            
set-strictmode -version latest            
            
$start=Get-Date            
$currentlog = $start.ToString()            
Write-Verbose "Starting $($myinvocation.mycommand)"            
Write-Verbose "Ready to put ServerName $ServerName in Maintenance Mode"            
            
            
Function Start-SCOMMaintenanceModeForServer            
{            
            
    [CmdletBinding(SupportsShouldProcess=$true)]            
      param            
      (            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='What is the server you want to put in Maintenance Mode?')]            
        [Alias("Server")]            
        [string[]]$ServerName,            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$false,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. This is a required parameter. Format is 1/29/2014 8:59:26 AM')]            
        [Datetime]$EndTime,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='PlannedOther, UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity')]            
        [string]$Reason,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Allows you to type a comment about the maintenance activity.')]            
        [string]$Comment,            
        [switch]$EventLog            
      )            
            
    Begin            
    {            
        Write-Verbose "Starting Function Start-SCOMMaintenanceModeForServer"            
        #Check for minumum Maintenance mode period of 5 mins.     
        
        $5MinFromNowTime = (GET-DATE).AddMinutes(5)
        $EndTime = [datetime]$EndTime
               
        if($EndTime -lt $5MinFromNowTime)              
        {            
            Write-Error "The time span for the maintenance mode should be at least 5 minutes." -ErrorAction Stop            
        }            
        Write-Verbose "Following server will be put in Maintenance Mode: $ServerName"            
        
        $MSs = Get-SCOMManagementServer                      
    } #End Begin            
            
    Process            
    {                    
            Write-Verbose "Checking if server $ServerName is not a Management Server"            
            if(($MSs | Select DisplayName) -eq $ServerName)            
            {            
                Write-Verbose "We don't want to put a Management Server in Maintenance Mode. Skipping"            
            }            
            else            
            {            
                Write-Verbose "Let's put server $ServerName in Maintenance Mode"            
                $Instance = Get-SCOMClassInstance -Name $ServerName            
                if ($PSCmdlet.ShouldProcess("Putting $ServerName in Maintenance Mode until $($Endtime).") )             
                {            
                    Write-Verbose ("Start-SCOMMaintenanceMode -Instance " + $Instance + " -EndTime " + $EndTime + " -Reason " + $Reason + " -Comment " + $Comment)
                    Start-SCOMMaintenanceMode -Instance $Instance -EndTime $EndTime -Reason $Reason -Comment $Comment      
                    New-MaintenanceWindow   
                }#End of whatif            
            }#End of else            
         
        if ($PSBoundParameters['EventLog'])            
        {                    
            write-eventlog -LogName "Operations Manager" -Source "OpsMgr SDK Service" -EventID 999 -message "The following Objects are put into in Maintenance Mode until $($EndTime) : $($ServerName)"            
        }#End if            
                    
    } #End Process            
            
    End            
    {            
        Write-Verbose "Finished Function Start-SCOMMaintenanceModeForServer Function"            
    }            
            
}            
            
#Main            
            
try            
{            
     if ($PSBoundParameters['EventLog'])            
     {                    
        write-eventlog -LogName "Operations Manager" -Source "OpsMgr SDK Service" -EventID 998 -message "The $($myinvocation.mycommand) is used to put Objects in Maintenance Mode"            
     }            
                 
     Write-Verbose "Checking if OperationsManager Module is loaded"            
     #Check if OperationsManager Module is loaded.            
     if(!(Get-Module OperationsManager))            
     {            
        Write-Verbose "Importing OperationsManager Module"            
        Import-Module OperationsManager -ErrorAction Stop            
     }            
            
     Write-Verbose "Checking for OM2012 environment"            
     #Check if OM2012 is being used.            
     if(!(Get-Module OperationsManager).Description -eq "Operations Manager OperationsManagerV10 Module")            
     {            
        Write-Error "This script is only for OM2012"            
     }            
            
    #Call Function            
     if ($PSBoundParameters['EventLog'])            
     {                    
        Start-SCOMMaintenanceModeForServer -ServerName $ServerName -EndTime $EndTime -Reason $Reason -Comment $Comment -EventLog            
     }            
     else            
     {            
        Start-SCOMMaintenanceModeForServer -ServerName $ServerName -EndTime $EndTime -Reason $Reason -Comment $Comment            
     }            
                
            
} #End Try            
            
catch [System.IO.FileNotFoundException]            
{            
    "OperationsManager Module not found"            
    $_.Exception.Message            
}            
            
catch            
{            
    Write-Warning "Oops something went wrong"            
    $_.Exception.Message            
}            
            
            
$end=Get-Date            
Write-Debug ("Total processing time {0}" -f ($end-$start).ToString())            
Write-Verbose "Ending $($myinvocation.mycommand)"
Any idea what I am doing wrong if I want to pass in the date in a format like this:  2/4/2014 4:26:00 PM
Free Windows Admin Tool Kit Click here and download it now
February 4th, 2014 3:17pm

Hi

You might try (Get-Date "2/4/2014 4:26:00") for $EndTime because it says http://technet.microsoft.com/en-us/library/hh918505(v=sc.20).aspx

Specifies when maintenance mode ends, as a DateTime object. A resource cannot be in maintenance mode for fewer than five minutes. To obtain a DateTime object, use the Get-Date cmdlet. For more information, type Get-Help Get-Date.

Cheers,

Stefan

February 4th, 2014 3:48pm

Thanks for your help.   I didn't see your response until just now, but I have been playing around with this all since my last response.   I got it to work.  I wish I could pinpoint what exactly I changed to get it to work, but I feel like I've been changing so much stuff that I'm not sure any more.

Just in case anyone finds it useful, here is the code.

          
[CmdletBinding(SupportsShouldProcess=$true)]            
        param            
        (            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='What is the server you want to put in Maintenance Mode?')]            
        [Alias("Server")]            
        [string[]]$ServerName,            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$false,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. This is a required parameter. Format is 1/29/2014 8:59:26 AM')]            
        [Datetime]$end,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='PlannedOther, UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity')]            
        [string]$Reason,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Allows you to type a comment about the maintenance activity.')]            
        [string]$Comment,            
        [switch]$EventLog            
        )            
            
set-strictmode -version latest            
            
#$start=Get-Date            
#$currentlog = $start.ToString()            
Write-Verbose "Starting $($myinvocation.mycommand)"            
Write-Verbose "Ready to put ServerName $ServerName in Maintenance Mode"            
            
            
Function Start-SCOMMaintenanceModeForServer            
{            
            
    [CmdletBinding(SupportsShouldProcess=$true)]            
      param            
      (            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='What is the server you want to put in Maintenance Mode?')]            
        [Alias("Server")]            
        [string[]]$ServerName,            
        [Parameter(Mandatory=$True,            
        ValueFromPipeline=$false,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. This is a required parameter. Format is 1/29/2014 8:59:26 AM')]            
        [Datetime]$end,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='PlannedOther, UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity')]            
        [string]$Reason,            
        [Parameter(Mandatory=$False,            
        ValueFromPipeline=$True,            
        ValueFromPipelineByPropertyName=$True,            
          HelpMessage='Allows you to type a comment about the maintenance activity.')]            
        [string]$Comment,            
        [switch]$EventLog            
      )            
            
    Begin            
    {            
        Write-Verbose "Starting Function Start-SCOMMaintenanceModeForServer"            
        #Check for minumum Maintenance mode period of 5 mins.     
        
        $start = Get-Date

        $5MinFromNowTime = $start.AddMinutes(5)
        #$end = [datetime]$end

        $end = $end.AddSeconds(5)
               
        if($end -lt $5MinFromNowTime)              
        {            
            Write-Error "The time span for the maintenance mode should be at least 5 minutes." -ErrorAction Stop            
        }            
        Write-Verbose "Following server will be put in Maintenance Mode: $ServerName"            
        
        $MSs = Get-SCOMManagementServer                      
    } #End Begin            
            
    Process            
    {                    
            Write-Verbose "Checking if server $ServerName is a Management Server" 
            #Write-Verbose ($MSs | Select DisplayName)           
            if(($MSs | Select DisplayName) -eq $ServerName)            
            {            
                Write-Verbose "We don't want to put a Management Server in Maintenance Mode. Skipping"            
            }            
            else            
            {            
                Write-Verbose "Let's put server $ServerName in Maintenance Mode"            
                $Instance = Get-SCOMClassInstance -Name $ServerName            
                if ($PSCmdlet.ShouldProcess("Putting $ServerName in Maintenance Mode until $($end).") )             
                {            
                    Write-Verbose ("Start-SCOMMaintenanceMode -Instance " + $Instance + " -EndTime " + $end + " -Reason " + $Reason + " -Comment " + $Comment)
                    Start-SCOMMaintenanceMode -Instance $Instance -end $end -Reason $Reason -Comment $Comment      
 
                }#End of whatif            
            }#End of else            
         
        if ($PSBoundParameters['EventLog'])            
        {                    
            write-eventlog -LogName "Operations Manager" -Source "OpsMgr SDK Service" -EventID 999 -message "The following Objects are put into in Maintenance Mode until $($end) : $($ServerName)"            
        }#End if            
                    
    } #End Process            
            
    End            
    {            
        Write-Verbose "Finished Function Start-SCOMMaintenanceModeForServer Function"            
    }            
            
}            
            
#Main            
            
try            
{            
     if ($PSBoundParameters['EventLog'])            
     {                    
        write-eventlog -LogName "Operations Manager" -Source "OpsMgr SDK Service" -EventID 998 -message "The $($myinvocation.mycommand) is used to put Objects in Maintenance Mode"            
     }            
                 
     Write-Verbose "Checking if OperationsManager Module is loaded"            
     #Check if OperationsManager Module is loaded.            
     if(!(Get-Module OperationsManager))            
     {            
        Write-Verbose "Importing OperationsManager Module"            
        Import-Module OperationsManager -ErrorAction Stop            
     }            
            
     Write-Verbose "Checking for OM2012 environment"            
     #Check if OM2012 is being used.            
     if(!(Get-Module OperationsManager).Description -eq "Operations Manager OperationsManagerV10 Module")            
     {            
        Write-Error "This script is only for OM2012"            
     }            
            
    #Call Function            
     if ($PSBoundParameters['EventLog'])            
     {                    
        Start-SCOMMaintenanceModeForServer -ServerName $ServerName -end $end -Reason $Reason -Comment $Comment -EventLog            
     }            
     else            
     {            
        Start-SCOMMaintenanceModeForServer -ServerName $ServerName -end $end -Reason $Reason -Comment $Comment            
     }            
                
            
} #End Try            
            
catch [System.IO.FileNotFoundException]            
{            
    "OperationsManager Module not found"            
    $_.Exception.Message            
}            
            
catch            
{            
    Write-Warning "Oops something went wrong"            
    $_.Exception.Message            
}            
            
            
$end=Get-Date            
Write-Debug ("Total processing time {0}" -f ($end-$start).ToString())            
Write-Verbose "Ending $($myinvocation.mycommand)"

There is one remaining problem with this script.   It does not correctly check to see if something is a management server. We have two management servers. These are the applicable lines, which I still haven't gotten to work yet. First, this retrieves the list of my Management servers:

            $MSs=Get-SCOMManagementServer     

Next, these lines are supposed to check if the server I specified is a management server:

            if(($MSs | Select DisplayName) -eq $ServerName)            
            {            
                Write-Verbose "We don't want to put a Management Server in Maintenance Mode. Skipping"            
            }  
Thanks to the Intellisense pop-up deal, I can see that $MSs does get my two management servers. And I can clearly see that there is a DisplayName column. And I can also see that the $ServerName does match what I put in my command line.   But it doesn't seem to catch them if they are actually equal to each other. I don't know if it's because there's two Management Servers, and it doesn't know how to compare like that? Any idea? Is there some sort of loop I need to write so that it compares is to the DisplayName for EACH Management Server it finds? Any help would be greatly appreciated.

Free Windows Admin Tool Kit Click here and download it now
February 4th, 2014 4:54pm

Hi

Well, one way would be if you just simply check if there is a SCOM Agent for this Server installed or not. If it is a Management Server, there will be no SCOM Agent, If there is a SCOM Agent you can be sure that the Server is monitored and it is not a SCOM Management Server, like this...

If (!(Get-SCOMAgent -Name $ServerName)) {Write-Host "Is Management Server / Or not SCOM managed"} else {Write-Host "Put into Maintenance Mode"}

Make sure $ServerName is in the FQDN Format.

Cheers,

Stefan

February 4th, 2014 9:32pm

What is the content of $instance?
In my environment, i use the following powershell and it work
server which is not management server
$instance=get-scomagent -name "abc.contoso.com"

Start-SCOMMaintenanceMode -Instance $Instance -EndTime "02/05/2014 15:26:00" -Reason "PlannedOther" -Comment "Testing Maintenance Mode"  

Roger

Free Windows Admin Tool Kit Click here and download it now
February 5th, 2014 3:40am

EndTim specifies when maintenance mode ends, as a DateTime object. A resource cannot be in maintenance mode for fewer than five minutes. To obtain a DateTime object, use the Get-Date cmdlet. For more information, type Get-Help Get-Date.

The following example puts a resource into maintenance mode for ten minutes.
The first command gets the class instance named Server01.Contoso.com by using the Get-SCOMClassInstance cmdlet.
The second command creates a DateTime object for ten minutes in the future and then stores it in the $Time variable.
The third command puts the resource defined by the object stored in the $Instance variable into maintenance mode. Maintenance mode ends at the time stored in the $Time variable. The command includes a reason for maintenance mode and a comment.

PS C:\> $Instance = Get-SCOMClassInstance -Name "Server01.Contoso.com"

PS C:\> $Time = ((Get-Date).AddMinutes(10))

PS C:\> Start-SCOMMaintenanceMode -Instance $Instance -EndTime $Time -Comment "Applying software update." -Reason "SecurityIssue"

February 5th, 2014 10:13am

Thanks for the help everyone, I think I have it all working now! That little trick to look to see if an SCOM agent is installed should do the trick!   I'm still re-arranging and tweaking my code a bit, but I believe I have what I need to finish up now.  Thanks again!

Free Windows Admin Tool Kit Click here and download it now
February 5th, 2014 1:58pm

Hi Niki,

I would like to know how to put the multiple servers in to maintenance mode whilst using your suggestion mentioned above?

Regards,

Srini

February 10th, 2015 2:47pm

http://xtremeownage.com/index.php?threads/start-scommaintenancemode-start-time-must-be-before-end-time-for-maintenance-mode.512/

This resolved the issue for me.

Free Windows Admin Tool Kit Click here and download it now
March 25th, 2015 5:17pm

http://xtremeownage.com/index.php?threads/start-scommaintenancemode-start-time-must-be-before-end-time-for-maintenance-mode.512/

This resolved the issue for me.

  • Proposed as answer by Eric Mcknight Wednesday, March 25, 2015 9:15 PM
March 25th, 2015 9:15pm

http://xtremeownage.com/index.php?threads/start-scommaintenancemode-start-time-must-be-before-end-time-for-maintenance-mode.512/

This resolved the issue for me.

  • Proposed as answer by Eric Mcknight Wednesday, March 25, 2015 9:15 PM
Free Windows Admin Tool Kit Click here and download it now
March 25th, 2015 9:15pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics