1

in my company we use powershell script that puts objects in maintenance mode. problem is that it suddently stop work at all - there are no errors, but script do nothing

maintenance intervals defines by XML file

for example

<MMWindow>
<Name>MMG 129OP SVC WEBSOA</Name>      ---group containing objects
<Schedule>Mon 19:30-Mon 23:00</Schedule> ---monday 19:30 to 23:00
</MMWindow>

and here is the script

$ErrorActionPreference = "stop"

$oAPI = new-object -comObject "MOM.ScriptAPI"
$Error.Clear()

If ($Debug -ne "true")
{
    $Debug = [bool]$false
}
else
{
    $Debug = [bool]$true
}

$DateTime = Get-Date
$Interval = $IntervalSeconds / 60

If ($Debug)
 { 
    $oAPI.LogScriptEvent("MaintenanceWindows.ps1",800,4,"The script 'MaintenanceWindows.ps1' is starting at $DateTime.")
 }

$setupKey = Get-Item -Path "HKLM:\Software\Microsoft\Microsoft Operations Manager\3.0\Setup"
$installDirectory = $setupKey.GetValue("InstallDirectory") | Split-Path
$psmPath = $installdirectory + "\Powershell\OperationsManager\OperationsManager.psm1"
Import-Module $psmPath
#Import-Module "C:\Program Files\System Center 2012\Operations Manager\Console\Microsoft.EnterpriseManagement.OperationsManager.ClientShell.dll"

New-SCOMManagementGroupConnection -ComputerName 123.ru
$XmlPath = "C:\Monitoring\Maintenance\MaintenanceWindows.xml"
[xml]$MMContent = Get-Content $XmlPath

If ($Debug -and $Error)
 { 
    $oAPI.LogScriptEvent("MaintenanceWindows.ps1",802,4,"Error: $Error. Time: $DateTime.")
 }

if ($MMContent.HasChildNodes)
{
    foreach ($MMWindow in $MMContent.MMWindows.MMWindow)
    {
       $ScheduledDays = ($MMWindow.Schedule).Split(",")

       foreach ($ScheduledDay in $ScheduledDays)
       {
            $StartDay = ($ScheduledDay.Split("-").GetValue(0)).Split(" ").GetValue(0)

             Switch ($StartDay)
            {
                "Mon" {$EndDay = "Monday"
                      $EndDayCount = 1}
                "Tue" {$EndDay = "Tuesday"
                      $EndDayCount = 2}
                "Wed" {$EndDay = "Wednesday"
                      $EndDayCount = 3}
                "Thu" {$EndDay = "Thursday"
                      $EndDayCount = 4}
                "Fri" {$EndDay = "Friday"
                      $EndDayCount = 5}
                "Sa" {$EndDay = "Saturday"
                      $EndDayCount = 6}
                "Su" {$EndDay = "Sunday"
                      $EndDayCount = 7}
            }

            $EndDay = ($ScheduledDay.Split("-").GetValue(1)).Split(" ").GetValue(0)

            Switch ($EndDay)
            {
                "Mon" {$EndDay = "Monday"
                      $EndDayCount = 1}
                "Tue" {$EndDay = "Tuesday"
                      $EndDayCount = 2}
                "Wed" {$EndDay = "Wednesday"
                      $EndDayCount = 3}
                "Thu" {$EndDay = "Thursday"
                      $EndDayCount = 4}
                "Fri" {$EndDay = "Friday"
                      $EndDayCount = 5}
                "Sa" {$EndDay = "Saturday"
                      $EndDayCount = 6}
                "Su" {$EndDay = "Sunday"
                      $EndDayCount = 7}
            }

            [DateTime]$StartTime = ($ScheduledDay.Split("-").GetValue(0)).Split(" ").GetValue(1)
            if ($EndDayCount -lt $StartDayCount)
            {
                [DateTime]$EndTime = ([DateTime]($ScheduledDay.Split("-").GetValue(1)).Split(" ").GetValue(1)).AddDays(7 - ($StartDayCount - $EndDayCount))
            }
            else
            {
                [DateTime]$EndTime = ([DateTime]($ScheduledDay.Split("-").GetValue(1)).Split(" ").GetValue(1)).AddDays($EndDayCount - $StartDayCount)
            }

            If ($StartDay -eq (Get-Date).DayOfWeek -and (Get-Date) -ge $StartTime.AddMinutes(-($Interval + 10)) -and (Get-Date) -lt $StartTime.AddMinutes($Interval + 10))
            {
                    $Group = Get-SCOMGroup -DisplayName $MMWindow.Name

            If ($Debug -and $Error)
            { 
                $oAPI.LogScriptEvent("MaintenanceWindows.ps1",803,4,"Error: $Error. Time: $DateTime.")
            }

                    If($Group)
                    {
                            $GroupMembers = $Group.GetRelatedMonitoringObjects()
                            If($GroupMembers.Count -gt 0)
                            {
                                Foreach ($Instance in $GroupMembers)
                                    {
                                    if (!$Instance.InMaintenanceMode)
                                    {
                                    Start-SCOMMaintenanceMode -Instance $Instance -EndTime $EndTime.ToUniversalTime() -Reason "PlannedOther"  -Comment "Planned Maintenance Mode by Script"
                                    $oAPI.LogScriptEvent("MaintenanceWindows.ps1",805,4, "Start MM for object: " + $Instance.DisplayName + ". End MM: " + $EndTime)
                            If ($Debug -and $Error)
                            { 
                                $oAPI.LogScriptEvent("MaintenanceWindows.ps1",804,4,"Error: $Error. Time: $DateTime.")
                            }
                                    }
                                }
                        }
                }
            }
        }
    }
}
If ($Debug)
 { 
    $oAPI.LogScriptEvent("MaintenanceWindows.ps1",801,4, "The script 'MaintenanceWindows.ps1' is finished.")
 }

any ideas?

Igor Kuznetsov
  • 421
  • 1
  • 6
  • 15
  • Have you run the script with debugging enabled? – Ansgar Wiechers Dec 08 '13 at 16:43
  • $ErrorActionPreference = "stop", it not enough? how to force ps to show all errors and warnings? like empty string an so on? i am not a programmer ( – Igor Kuznetsov Dec 09 '13 at 16:53
  • Setting `$ErrorActionPreference = "Stop"` should make the script print an error message and terminate in case of an error. However, depending on how you run it you may or may not see the message. Also, the script looks like it was written with a different kind of error handling in mind. – Ansgar Wiechers Dec 09 '13 at 17:00
  • i put if ($Group -eq $null) { Write-Host "Group is empty"} before If($Group) , so, at least group is not empty... anyway- how to turn on all debug in that case? – Igor Kuznetsov Dec 09 '13 at 20:00
  • Normally you'd just have to run the script with the parameter `-Debug`. However, since whoever wrote the script was apparently somewhat less than educated about PowerShell argument handling this won't work here. Instead you need to set `$Debug = "true"` before running the script. – Ansgar Wiechers Dec 09 '13 at 22:01
  • @AnsgarWiechers Shouldn't that be `$DebugPreference = "Continue"` (I've never seen any doc on $debug) – Χpẘ Dec 10 '13 at 02:24
  • @user2460798 No. Take a look at the beginning of the script: it's checking a value `$Debug` for a string value `"true"`. Therefore this variable must be set somewhere before this check. The simplest way to do this is by setting the variable before running the script (`$Debug = "true"; .\script.ps1`). This doesn't have anything to do with the standard PowerShell configuration variables. – Ansgar Wiechers Dec 10 '13 at 13:37
  • Thanks a lot. Looks like problems was in xml. Now $group is not epmty. Will share thise script too SCOM community after tests – Igor Kuznetsov Dec 10 '13 at 19:57

2 Answers2

0

As Ansgar indicated a good way to address a problem like that is via some sort of debugging.

However you asked for ideas, so here are some: 1. One likely way I see for the script to do "nothing" (assuming it runs at all) is for $GroupMembers to be empty. 2. $GroupMembers relies on $Group evaluating to $true, so if $Group is $null nothing will happen. 3. $Group isn't assigned unless the following evaluates $true:

$StartDay -eq (Get-Date).DayOfWeek -and 
(Get-Date) -ge $StartTime.AddMinutes(-($Interval + 10)) -and 
(Get-Date) -lt $StartTime.AddMinutes($Interval + 10))
  1. That expression being $true depends on the value of $Interval. $Interval is defined based on $IntervalSeconds - whose definition is not shown in the OP. So StackOverflow responders can't help you with that code path.

  2. A couple of other possible failures are Get-SCOMGroup returning $null or GetRelatedMonitoringObjects returning $null.

Since the original question asked for ideas and I gave you several plausible ideas, I'd say I answered the question.

Χpẘ
  • 3,403
  • 1
  • 13
  • 22
  • intervalseconds=300. anyway to turn on all errors and warnings? – Igor Kuznetsov Dec 09 '13 at 16:37
  • A lot of Powershell cmdlets can give verbose and/or debug output. Run `help about_preference_variables` and look for $DebugPreference and $VerbosePreference. Set-StrictMode can be used to find some kinds of (generally coding) errors. Trace-Command can be used to get a huge amount of internal info. However in your case, you're probably better off by adding some debug statements (I use `write-host` when I debug) to your script. Also looks like the answer from @Start-Automating has info specific to SCOM maintenance mode. – Χpẘ Dec 10 '13 at 02:16
0

My company wrote these cmdlets for Microsoft a couple of years ago. This question rung a bell about a SCOM enthusiast friend and the need to change maintenance modes often. I checked, and I believe that the commands Start-SCOMMaintenanceMode and Update-SCOMMaintenanceMode will do the trick (and save you a bunch of code).

Please let me know if this is not the case.

Start-Automating
  • 8,067
  • 2
  • 28
  • 47