Creating an audible alert notification in SCOM
Posted by Jeremy D. Pavleck on September 12th, 2008
Edit: 09/13/2008 - On the advice of Pete Zerger, updated script to include a throttling mechanism to prevent an overload if an alert storm occurs. Also changed things around to make it a more generic ‘run remote executable’ instead of run remote sound.
A question was recently asked on the MOM Mailing List over at myITforum.com.
That question was, quite to the point:
“How to create a audible alert? I like to create one for the critical alerts..”
I’ve been working earlier with a script that would go out and disable the run time tracing, stop it, then delete the log files. So I already had knew what would work - a simple PowerShell script that uses WMI’s process create method on a remote machine.
A caveat lector before I continue; while this solution will technically work, I haven’t tested it formally. Additionally, you’ll need to contend with permission issues that arise as well. If you’re running the OpsMgr services under a named account, you’ll need to give that same account local administrator access on whichever machine you plan to run this call against. If you’re using ‘Local System’ you’ll have to either add the RMS\Local System account to the remote machine’s admin group or embed credentials inside the WMI call((Be careful when doing this. I haven’t included directions for that because it’s just a nightmare waiting to happen. I can give you a jumping off point though.))
First, the script. It’s small and basic. It wants to know the machine you want to run the command on, the command, and because this is a a sound player, the path to the WAV file. It then creates the process via WMI, and decodes the return code. If it’s 0, everything is fine. If it’s anything else, the process creation failed and it writes an event to the Operations Manager event log, which you can create an additional rule to look for.
Download SCOM-RunRemoteExecutable.ps1
#
# Microsoft PowerShell Source File — Created with SAPIEN Technologies PrimalScript 2007
#
# NAME: SCOM-RunRemoteExecutable.ps1
#
# AUTHOR: Jeremy D. Pavleck , Pavleck.NET
# DATE : 9/13/2008
#
# COMMENT: This is a Proof Of Concept script written in response to a mailing list request to
# enable OpsMgr to sound an audible alert on a remote admin PC, such as a console in a
# NOC.
# This is to be run as a Notification Command Channel.
#
# NOTES/WARNING: This script uses a remote WMI call to spawn a process on a named server. As
# such, there are security issues to keep in mind. I haven’t added the code to allow you
# to use alternate credentials, but use http://poshcode.org/501 as a jumping off point.
# If you’re running the OpsMgr services under a domain account, add that user to the local
# administrators group on the machine you want to run this command. If you’re using local
# system, add RMS\Local System to the admin group.
# RUN AT YOUR OWN RISK!
#
# VERSIONS:
# v1.0 - 09/12/2008 - Initial version
# v1.1 - 09/13/2008 - On the advice of Pete Zerger, added a throttling routine to prevent
# to many executions during an alert storm
# v1.2 - 09/13/2008 - Changed variable names to make it a more ‘run remote executable’ script
#
# ==============================================================================================
# User Settings
$remoteMachine = "adminconsole.pavleck.net"
# The location to the executable. This is the path on the REMOTE machine.
$myExe = "C:\Program Files\Real Alternative\Media Player Classic\mplayerc.exe"
$myExeParams = "C:\Windows\Media\tada.exe" # Paramters to pass to the executable, such as the location of the sound file, etc.
# Leave blank if none are needed
# Registry & throttling settings
$myKey = "SCOM_PowerShell_Scripts" # Reg key name to use
$myValueName = "LastRunTime" # Data value
$interval = 5 # Wait at least this long, in minutes
# Initialize a couple things
$firstRun = $False
$throttle = $False
# We use the OpsMgr API only because it’s a very quick and simple way to log to the eventviewer
$momAPI = New-Object -comObject "MOM.ScriptAPI"
# LogScriptEvent Severities
$momErr = 1
$momWarn = 2
$momInfo = 4
# Setup some event ids to use
$errID = 11000
$warnID = 11001
$infoID = 11002
$myName = $MyInvocation.MyCommand.Name # Grab script name
### Registry throttling settings
# First see if our key exists, if not, create it and populate it with the current date/time
# and set $firstRun to $True
If(!$(Test-Path HKLM:\SOFTWARE\$myKey)) {
New-Item -Path HKLM:\Software\$myKey
New-ItemProperty -Path HKLM:\SOFTWARE\$myKey -Name $myValueName -Value (Get-Date)
$firstRun = $True
}
# If this isn’t the first run, compare previous time with current time - if last run is $interval
# minutes ago or higher, carry on, otherwise exit
If(!($firstRun)) {
$lastRun = (Get-ItemProperty -Path HKLM:\SOFTWARE\$myKey).$myValueName
Set-ItemProperty -Path HKLM:\SOFTWARE\$myKey -Name $myValueName -Value (Get-Date)
If(((Get-Date) - [DateTime]$lastRun).TotalMinutes -ge $interval) {
$throttle = $False
} else {
$throttle = $True
}
}
# Function DecipherRetCode accepts an integer, and returns the failure assigned to that code.
# This only returns the most common failures, such as permissioning and the like
Function DecipherRetCode([int]$retCode) {
switch ($retCode) {
0 {return "Success"}
2 {return "Access Denied"}
3 {return "Insufficient Privilege"}
8 {return "Unknown Failure"}
21 {return "Invalid Parameter"}
default {return "$($retCode) is uncommon, and will need to be researched manually. "}
}
}
# This line is actually the entire script.
If($throttle) {
# Throttling - cancel response
$momAPI.LogScriptEvent($myName, $warnID, $momWarn, "Notification Workflow requested that $($myname) run, but last response ran less then $($interval) minutes ago. Exiting.")
$momAPI = $null
exit
} else {
$retCode = ([WMICLASS]"\\$remoteMachine\root\cimv2:win32_process").Create("$myExe $myExeParams")
# If $retCode = 0 ($false) exit the If, anything else is $True, and will log it
If($retCode) {
$momAPI.LogScriptEvent($myName, $errID, $momErr, "Error creating process. Error Code: $($retcode) Error Message: $(DecipherRetCode $retCode)")
}
$momAPI = $null
exit
}
To implement this, open the Operations Console and go to Administration > Settings > Notification
Click on the Command tab, then click on add. Fill it out as you normally would:

Then click on OK, and you’ll see it with the rest of your commands:

Now to finish it up you’ll need to create a new notification recipient. Right-click on Notifications and select new recipient.
Make the display something to designate that it runs a command, I used “Sound Audible Alert”. And because the NOC isn’t manned 24/7, I limited the notification time to weekdays from 8am to 6pm. You can also adjust this from the devices tab, but I’m not going to include an emailing or other devices, so I prefer to set it in the general tab, this way it’s obvious even with a casual glance what the settings are.

After that, click on the “Notification Devices” tab, then click “Add”.
In the resulting popup, select our new notification command and enter anything for the delivery address - I used NA, because for this particular command we don’t require any additional information - but OpsMgr still needs something in there. Hit next, keep the schedule at always unless you’re adding additional channels, next again, name the device - I used “Send Audible Alert”

Click OK, and your set. Treat it like any other notification recipient - either create a new rule just for this, or edit an existing subscription and add our new recipient to it.
As you can see, using PowerShell inside of Operations Manager makes it very flexible and powerful. We can run all manner of things in response to alerts; From running a simple sound file all the way up to initiating disaster recovery scenarios and intense system diagnostics - both things which I’ll be showing you later on as we explore the Notification Command Channel together.



