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: http://blogs.technet.com/b/kevinholman/archive/2009/07/22/101-using-custom-scripts-to-write-events-to-the-opsmgr-event-log-with-momscriptapi-logscriptevent.aspx

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.