• The First-Ever Dutch PowerShell User Group

    Last Friday we had our first ever Dutch PowerShell User Group meeting and I could finally meet Ed Wilson and his wife Teresa.

    Read more on the Hey, Scripting Guy! Blog

  • Update: Put OM2012 Computer Group Members in Maintenance Mode with PowerShell

    I finally found out the issue why this script was not working for everybody. It was because of the different versions of PowerShell. Now it should also work on PowerShell v2.

    Another possible fix to the empty ComputerGroupsMembernames issue.

    Last week I saw a request for a PowerShell script which would put all the members of a OM2012 Computer Group in Maintenance Mode, so this could be used with the Task Scheduler.

    I know there are quite some alternative when it comes to putting instances in Maintenance Mode, but I thought it would be cool to create the mother-of-all maintenance mode PowerShell scripts for OM2012 :-)

    This PowerShell script can be run standalone or scheduled with the Task Scheduler and has the following cool features:

    • Acts as a “real” Cmdlet, with features like:
      • Verbose info
      • Debug info
      • WhatIf switch
    • Help info with Examples
    • Write to Eventlog switch for auditing purposes.
    • No need to run it from the Operations Manager Shell. If the OperationsManager Module is not loaded it will be loaded automatically by the script.

     

    Ok enough about the features, here is the script:

    #######################################################################################################################             
    # Puts a OM2012 Computer Group in Maintenance Mode using PowerShell             
    # Author: Stefan Stranger (Microsoft)             
    # Example usage: Run Get-Help Get-SCOMMaintenanceModeForGroups.ps1 -Examples            
    # Disclamer: This program source code is provided "AS IS" without warranty representation or condition of any kind            
    # either express or implied, including but not limited to conditions or other terms of merchantability and/or            
    # fitness for a particular purpose. The user assumes the entire risk as to the accuracy and the use of this            
    # program code.            
    # Tested on PowerShell v3 and OM2012 environment             
    # Date: 03-07-2012             
    # Name: Get-SCOMMaintenanceModeForGroups.ps1             
    # v1.000 - 03-07-2012 - Stefan Stranger - initial sstranger's release            
    # v1.001 - 06-07-2012 - Stefan Stranger - Added Eventlog and WhatIf Switch 
    # v1.003 - 07-11-2012 - Stefan Stranger - Fixed issue on PowerShell v2, Now works on v2 and v3 # v1.004 - 16-11-2012 - Stefan Stranger - Fixed issue with empty GroupMembershipNames issue
    ######################################################################################################################## <# .SYNOPSIS Places all members of a SCOM Computer Group in into maintenance mode, and creates new active maintenance mode entries. .DESCRIPTION The Start-MaintenanceModeForGroups script places all members of a SCOM Computer Group into maintenance mode, and creates new active maintenance mode entries. When in maintenance mode, alerts, notifications, rules, monitors, automatic responses, state changes, and new alerts are suppressed for the class instance. .EXAMPLE Start-SCOMMaintenanceModeForGroup.ps1 -ComputerGroup "All Windows Computers" -EndTime 10 -Reason "UnplannedOther" -Comment "Testing Maintenance Mode" -Verbose Puts all Members of the "All Windows Computer" Group in Maintenance Mode for 10 minutes, with Reason "UnplannedOther" and with Comment "Testing Maintenance Mode". Adding Verbose information. .EXAMPLE Start-SCOMMaintenanceModeForGroup.ps1 -ComputerGroup "All Windows Computers" -EndTime 10 -Reason "UnplannedOther" -Comment "Testing Maintenance Mode" -Eventlog Puts all Members of the "All Windows Computer" Group in Maintenance Mode for 10 minutes, with Reason "UnplannedOther" and with Comment "Testing Maintenance Mode". Writing Eventlog information to the "Operations Manager" Eventlog (eventid 998 and eventid 999). Can be used for tracking and debugging when Task Scheduler is being used. .EXAMPLE Start-SCOMMaintenanceModeForGroup.ps1 -ComputerGroup "All Windows Computers" -EndTime 10 -Reason "UnplannedOther" -Comment "Testing Maintenance Mode" -WhatIf Using the WhatIf switch shows which Members of the "All Windows Computer" Group would be put in Maintenance Mode if you had run the script. So the members are not really put into maintenance mode. For testing purposes. .PARAMETER ComputerGroup The SCOM Computer Group name for which members you want to put in Maintenance Mode. .PARAMETER EndTime Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. .PARAMETER Reason Specifies the reason for placing the resource into maintenance mode. Valid values are: UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity .Parameter Comment Allows you to type a comment about the maintenance activity. .Parameter EventLog Writes information to the "Operations Manager" Eventlog to track what is happening. .Link http://blogs.technet.com/stefan_stranger#> #requires -version 2.0 [CmdletBinding(SupportsShouldProcess=$true)] param ( [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the ComputerGroup you want to put in Maintenance Mode?')] [Alias("Group")] [string[]]$ComputerGroup, [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')] [int]$EndTime, [Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='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 ComputerGroup $ComputerGroup in Maintenance Mode" Function Start-SCOMMaintenanceModeForGroup { <# .SYNOPSIS Sets a SCOM Group in Maintenance Mode .DESCRIPTION Sets the members of a SCOM Group in Maintenance Mode .EXAMPLE Start-SCOMMaintenanceModeForGroup -ComputerGroup "All Windows Computers" -EndTime 10 -Reason "UnplannedOther" -Comment "Testing Maintenance Mode" -Verbose .PARAMETER ComputerGroup The SCOM Computer Group name for which members you want to put in Maintenance Mode. .PARAMETER EndTime Specifies the time the maintenance will end. The minimum amount of time a resource can be in maintenance mode is 5 minutes. .PARAMETER Reason Specifies the reason for placing the resource into maintenance mode. Valid values are: UnplannedOther, PlannedHardwareMaintenance, UnplannedHardwareMaintenance, PlannedHardwareInstallation, UnplannedHardwareInstallation, PlannedOperatingSystemReconfiguration, UnplannedOperatingSystemReconfiguration, PlannedApplicationMaintenance, ApplicationInstallation, ApplicationUnresponsive, ApplicationUnstable, SecurityIssue, LossOfNetworkConnectivity .Parameter Comment Allows you to type a comment about the maintenance activity. .Link http://blogs.technet.com/stefan_stranger #> [CmdletBinding(SupportsShouldProcess=$true)] param ( [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='What is the ComputerGroup you want to put in Maintenance Mode?')] [Alias("Group")] [string[]]$ComputerGroup, [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')] [int]$EndTime, [Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage='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-SCOMMaintenanceModeForGroup Function" #Check for minumum Maintenance mode period of 5 mins. if($endtime -lt 5) { Write-Error "The time span for the maintenance mode should be at least 5 minutes." -ErrorAction Stop } Write-Verbose "Following Group Members will be put in Maintenance Mode:" $ComputerGroupMembers = Get-SCOMMonitoringObject -DisplayName $ComputerGroup if($ComputerGroupMembers) { #$ComputerGroupMemberNames = ($ComputerGroupMembers.getrelatedMonitoringObjects() | select DisplayName).DisplayName
    $ComputerGroupMemberNames = ($ComputerGroupMembers.getrelatedMonitoringObjects() | select DisplayName)
    Write-Verbose "$ComputerGroupMemberNames" #Retrieve Management Servers so we can check if we don't put Management Servers in MM. $MSs = Get-SCOMManagementServer } else { Write-Error "No Members of ComputerGroup $ComputerGroup found" -ErrorAction Stop } } #End Begin Process { #Put Agents in Maintenance Mode foreach ($agent in $ComputerGroupMembers.getrelatedMonitoringObjects()) { Write-Verbose "Checking if ComputerGroup Member $agent is not a Management Server" if(($MSs | Select DisplayName) -eq $agent) { Write-Verbose "We don't want to put a Management Server in MM. Skipping" } else { Write-Verbose "Let's put Agent $Agent in Maintenance Mode" $Instance = Get-SCOMClassInstance -Name $Agent if ($PSCmdlet.ShouldProcess("Putting $Agent in Maintenande Mode for $($Endtime) minutes") ) { #Added 5 seconds to EndTime to prevent failing the Start-SCOMMaintenanceMode cmdlet. Min. 5 mins is needed. Start-SCOMMaintenanceMode -Instance $Instance -EndTime ([System.DateTime]::Now).AddSeconds(5).addMinutes($EndTime) -Reason $Reason -Comment $Comment }#End of whatif }#End of else }#End Foreach if ($PSBoundParameters['EventLog']) { write-eventlog -LogName "Operations Manager" -Source "OpsMgr SDK Service" -EventID 999 -message "The following Objects are put into in Maintenance Mode for $($EndTime) minutes: $($ComputerGroupMembers.getrelatedMonitoringObjects())" }#End if } #End Process End { Write-Verbose "Finished Function Start-SCOMMaintenanceModeForGroup 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-SCOMMaintenanceModeForGroup -ComputerGroup $ComputerGroup -EndTime $EndTime -Reason $Reason -Comment $Comment -EventLog } else { Start-SCOMMaintenanceModeForGroup -ComputerGroup $ComputerGroup -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)"

     

    You can use the Get-Help Get-SCOMMaintenanceModeForGroups.ps1 –full command in PowerShell to see the complete help for this script.

    image

    Example using the –WhatIf switch

    image

    Let’s do the real deal and put some members of my “Stefan – OM2012 Maintenance Computer Group” in Maintenance Mode for 5 minutes.

    image

    Result:

    image

    image

     

    How do use this cool PowerShell script to schedule Maintenance Mode using the Task Scheduler?

    Steps:

      1. Save script as: D:\Scripts\OM2012\Start-SCOMMaintenanceModeForGroups.ps1

      2. Open TaskScheduler (on OM2012 Management Server or where you have installed the Operations Manager Console)
        image

      3.  

        Create a new Task
        image

         

      4. Enter Name and make sure the user account under which the Scheduled Task is running is having enough permissions in SCOM. Select Run with Highest privileges.
        image

      5. Configure Trigger
        image

      6. Add action

        Program/script: powershell.exe

        Add argument (optional): D:\Scripts\OM2012\Start-SCOMMaintenanceModeForGroups.ps1 -ComputerGroup 'Stefan - OM2012 Maintenance Computer Group' -EndTime 5 -Reason "UnplannedOther" –Comment 'Testing MM' -Eventlog

        Remark: Make sure you use single quotes of ComputerGroup, Reason or Comment Parameters if space are being used in the name.

        image

      7. Enter Credentials

        clip_image001

        clip_image002

        clip_image003

    If you have scheduled to script using the EventLog Switch toy can look in the Operations Manager Eventlog for auditing info.
    image

    You can download the script from the Script Center Repository: http://gallery.technet.microsoft.com/scriptcenter/Put-OM2012-Computer-Group-43902672

    Have fun!

  • Get-SCOMAlert Cmdlet, the Criteria Parameter and the Non-Equal Operator

    Wow, that is a cryptic blogtitleWinking smile Did I already lost you people with this blogpost title? I hope not, because this blogpost is about how to use the Get-SCOMAlert Cmdlet using the Criteria parameter the correct way.

    Credits for this blogpost go to my colleague Jens Morawietz, because he explained the implications of using the Get-SCOMAlert Cmdlet with the Criteria parameter to me.

    Let’s first start at looking at the help for the Get-SCOMAlert Cmdlet.

    Get-Help Get-SCOMAlert

    image

     

    If we look at the Examples for this Cmdlet we don’t find much information about the Criteria Parameter

    image

     

    So let’s explore the Criteria Parameter.

    If we want to retrieve all New Alerts with a severity Critical and the Alert being generated by a Monitor we can use the following Command:

    Get-SCOMAlert -Criteria "ResolutionState = 0 AND Severity = 2 AND IsMonitorAlert = 1"

    image

     

     

    The reason we should use the Criteria parameter instead of filtering using the Where-Object Cmdlet is because of the impact on performance. If we use the Where-Object Cmdlet we first retrieve ALL Alerts before filtering.

    Get-SCOMAlert | Where-Object {$_.ResolutionState -eq 0 -and $_.Severity -eq 2 -and $_.IsMonitorAlert -eq 1}

    Same result:

    image

    But if we compare the time it takes to complete both commands we see a difference.

    image

    Using the Criteria Parameter is much faster and less resource intensive.

    Now we are convinced using the Criteria Parameter there is something you need to know when using this parameter and that is that the criteria parameter method will return only the alerts where the field is set to a value not equal to the given value and the PS method will return the alerts where the field is set to a value not equal to the given value OR is NULL, e.g.:

    Let’s try to retrieve all New Alerts with a Severity Critical and the Alert being generated by a Monitor AND the Owner not being “Stefan”

    image

     

    We would think we could use the following statement to retrieve those Alerts:

    Get-SCOMAlert -Criteria "ResolutionState = 0 AND Severity = 2 AND IsMonitorAlert = 1 AND (Owner <> 'Stefan')"

     

    But when we run these commands we see no Alerts being returned. Sad smile

    image

    Wen we use the Where-Object Cmdlet we see that there are Alerts where the owner is not “Stefan”

    Get-SCOMAlert | Where-Object {$_.ResolutionState -eq 0 -and $_.Severity -eq 2 -and $_.IsMonitorAlert -eq 1 -AND $_.Owner -ne "Stefan"}

     

    image

     

    So the resolution is to include OR <property> IS NULL in the criteria, which is in the end the WHERE clause of the SELECT statement on the Ops Mgr db, e.g.:

    Get-SCOMAlert -Criteria "ResolutionState = 0 AND Severity = 2 AND IsMonitorAlert = 1 AND (Owner <> 'Stefan' OR Owner IS NULL)"

    image

     

    Btw, the last method is not only less resource consuming but much faster than the second one.

     

    Have fun and thanks Jens for explaining.