# ==============================================================================================
#
# 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
}