Menu Close

SCOM Authoring – script based monitor with script based recovery

Had a customer asking about how to create a monitor that would count the number of files in a folder, and then run a script based recovery to take an action (restart a service) afterwards.

This is not a complicated request, but probably a common scenario.  There are lots of examples on the web for the pieces and parts.  Lets just put it all together.

This MP will be using:

The file count script from: http://www.scom2k7.com/scom-2007-script-to-monitor-file-count-inside-a-directory/

The script restart from: http://blogs.catapultsystems.com/cfuller/archive/2011/07/06/automating-the-restart-of-a-service-in-opsmgr.aspx

I will add the event logging from: https://kevinholman.com/2009/07/22/scom-101-using-custom-scripts-to-write-events-to-the-opsmgr-event-log-with-momscriptapi-logscriptevent/

You can create this simple MP in the SCOM UI (two state monitor, script based) or any other authoring tool.  I’ll be showing the XML

The manifest is super simple:

<Manifest> <Identity> <ID>Demo.ScriptMonitor.Files</ID> <Version>1.0.0.1</Version> </Identity> <Name>Demo.ScriptMonitor.Files</Name> <References> <Reference Alias="Windows"> <ID>Microsoft.Windows.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="System"> <ID>System.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="SystemCenter"> <ID>Microsoft.SystemCenter.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> <Reference Alias="Health"> <ID>System.Health.Library</ID> <Version>6.1.7221.0</Version> <PublicKeyToken>31bf3856ad364e35</PublicKeyToken> </Reference> </References> </Manifest>

The monitor is a simple Microsoft.Windows.TimedScript.TwoStateMonitorType

It runs a script (see below) every 10 minutes, counting files in a folder.  We pass two parameters, the folder location and the file count threshold.

<Monitors> <UnitMonitor ID="Demo.ScriptMonitor.Files.FileCountMonitor" Accessibility="Public" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Windows!Microsoft.Windows.TimedScript.TwoStateMonitorType" ConfirmDelivery="false"> <Category>Custom</Category> <AlertSettings AlertMessage="Demo.ScriptMonitor.Files.FileCountMonitor_AlertMessageResourceID"> <AlertOnState>Warning</AlertOnState> <AutoResolve>true</AutoResolve> <AlertPriority>Normal</AlertPriority> <AlertSeverity>Warning</AlertSeverity> <AlertParameters> <AlertParameter1>$Data/Context/Property[@Name='ret2']$</AlertParameter1> <AlertParameter2>$Data/Context/Property[@Name='ret']$</AlertParameter2> </AlertParameters> </AlertSettings> <OperationalStates> <OperationalState ID="Demo.ScriptMonitor.Files.FileCountMonitor.Good" MonitorTypeStateID="Success" HealthState="Success" /> <OperationalState ID="Demo.ScriptMonitor.Files.FileCountMonitor.Bad" MonitorTypeStateID="Error" HealthState="Warning" /> </OperationalStates> <Configuration> <IntervalSeconds>600</IntervalSeconds> <SyncTime /> <ScriptName>CountFiles.vbs</ScriptName> <Arguments>"C:\test" 5</Arguments> <ScriptBody>Dim oAPI, oBag, objFSO, objFldr, bSendError, strOut bSendError = False Set oAPI = CreateObject("MOM.ScriptAPI") Call oAPI.LogScriptEvent("CountFiles.vbs",6001,0,"Starting countfiles script") Set oBag = oAPI.CreateTypedPropertyBag(StateDataType) Set eBag = oAPI.CreateTypedPropertyBag(StateDataType) Set oArgs = WScript.Arguments If oArgs.Count &lt; 2 Then strReturn = "Script aborted. Not enough parameters provided" Call eBag.AddValue("State","BAD") Call eBag.AddValue("ret",strReturn) Call oAPI.Return(eBag) WScript.Quit -1 End If strOut = checkfolder(oArgs(0),int(oArgs(1))) If bSendError Then strReturn = strOut Call oBag.AddValue("State","BAD") Call oBag.AddValue("ret2", objFldr.Files.Count) Call oBag.AddValue("ret",strReturn) Else 'WScript.Echo("GOOD "&amp; vbNewLine &amp; strOut) Call oBag.AddValue("State","GOOD") End If if 0 &lt;&gt; Err.number Then strReturn = "An Error occured: " &amp; Err.Description Call eBag.AddValue("State","BAD") Call eBag.AddValue("ret",strReturn) Call oAPI.Return(eBag) else Call oAPI.Return(oBag) end if Function checkfolder(strfldname,numberfiles) Set objFSO=CreateObject("Scripting.FileSystemObject") Set objFldr=objFSO.GetFolder(strfldname) If objFldr.Files.Count &gt; numberfiles Then checkfolder = numberfiles bSendError = True End If End Function </ScriptBody> <TimeoutSeconds>60</TimeoutSeconds> <ErrorExpression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Property[@Name='State']</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">BAD</Value> </ValueExpression> </SimpleExpression> </ErrorExpression> <SuccessExpression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">Property[@Name='State']</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">GOOD</Value> </ValueExpression> </SimpleExpression> </SuccessExpression> </Configuration> </UnitMonitor> </Monitors>

Next we add a recovery.  This simple recovery script restarts the spooler service anytime the monitor goes into an unhealthy state.

<Recoveries> <Recovery ID="Demo.ScriptMonitor.Files.RecoveryRestartService" Accessibility="Public" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" Monitor="Demo.ScriptMonitor.Files.FileCountMonitor" ResetMonitor="false" ExecuteOnState="Warning" Remotable="true" Timeout="300"> <Category>Custom</Category> <WriteAction ID="Demo.ScriptMonitor.Files.WA" TypeID="Windows!Microsoft.Windows.ScriptWriteAction"> <ScriptName>RestartService.vbs</ScriptName> <Arguments /> <ScriptBody>Option Explicit Dim oAPI, strServiceName, objWMIService, colListOfServices, objService Set oAPI = CreateObject("MOM.ScriptAPI") Call oAPI.LogScriptEvent("RestartService.vbs",5555,2,"Recovery - Starting recovery script to restart service") WScript.sleep 3000 Call oAPI.LogScriptEvent("RestartService.vbs",5556,2,"Recovery - Attempting service stop") 'Stop Service strServiceName = "spooler" Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name ='" &amp; strServiceName &amp; "'") For Each objService in colListOfServices objService.StopService() Next WScript.sleep 5000 Call oAPI.LogScriptEvent("RestartService.vbs",5557,2,"Recovery - Attempting service start") 'Start Service strServiceName = "spooler" Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") Set colListOfServices = objWMIService.ExecQuery ("Select * from Win32_Service Where Name ='" &amp; strServiceName &amp; "'") For Each objService in colListOfServices objService.StartService() Next WScript.sleep 5000 WScript.Quit</ScriptBody> <TimeoutSeconds>60</TimeoutSeconds> </WriteAction> </Recovery>

That’s it!

I am attaching the sample XML below.

Demo.ScriptMonitor.Files.zip

Leave a Reply

Your email address will not be published.