I ran into an issue where I needed to count the number of xml files in a directory. The problem was there are 10,000 other files in the directory. The application team didn’t care about the extra files and didn’t want to clean them out. All they wanted to know was when the number of XML files was over 15.
First I tried a basic vb script, like this.
Set objFSO=CreateObject(“Scripting.FileSystemObject”)
Set oArgs = WScript.Arguments
FolderName = oArgs(0)
Set objFolder=objFSO.GetFolder(FolderName)
Set Dirfiles = objFolder.Files
Int filecount = 0
For each file In Dirfiles
sext = objFSO.GetExtensionName(file.Path)
If LCase(sext) = “xml” Then
filecount = filecount+1
End If
Next
WScript.Echo filecount
This works fine in a directory with only a few files but my directory has 10,000 other files in it. I ran this script waited 10 minutes and then canceled it. Obviously this was not going to work as the script has to touch every file in the directory. Operations Manager would time out way before the script finishes.
So after many Google and Bing searches looking for a different vb scripts to count only the xml files, I decided to see how easy it would be in C#.
In C# it was a piece of cake. You can download the C# project file with source here.
https://www.scom2k7.com/downloads/filecount.zip
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace filecount
{
class Program
{
static void Main(string[] args)
{
string directoryPath = args[0];
string eXtension = “*.” + args[1];
int fileCount = System.IO.Directory.GetFiles(directoryPath,
eXtension).Length;
Console.WriteLine(fileCount);
}
}
}
I ran the executable that visual studio created with two parameters “directory” and “extension” and it took one second to count the number of xml files in the directory. This is what I was looking for, way faster and more efficient.
So now I have a working executable the takes two parameters. How do I get it to work with SCOM?
The easiest way was to remove the Console.WriteLine(fileCount) and set the count to the exit code.
Environment.Exit(fileCount);
Now all I need to do is wrap this executable with a vbscipt and have SCOM call it. You can download the vb script here. https://www.scom2k7.com/downloads/advanced.zip
Dim oAPI, oBag, objShell, objFSO, objFile, myCMD, bWaitOnReturn, returnCmd, oArgs
Set oAPI = CreateObject(“MOM.ScriptAPI”)
Set oBag = oAPI.CreateTypedPropertyBag(StateDataType)
Set oArgs = WScript.Arguments
If oArgs.Count < 3 Then
Call oAPI.LogScriptEvent(“FileCountCSharp.vbs”, 500, 0, “Script aborted. Not enough parameters provided.”)
WScript.Quit -1
End If
folder = oArgs(0)
extension = oArgs(1)
userCount = cint(oArgs(2))
bWaitOnReturn= True
Set objShell=CreateObject(“WScript.Shell”)
Set objFSO=CreateObject(“Scripting.FileSystemObject”)
strPath=“C:\ScomTools\filecount.exe”
If objFSO.FileExists(strPath) Then
set objFile=objFSO.GetFile(strPath)
myCMD = strPath & ” “ & folder & ” “ & extension
returnCmd = objShell.Run (myCMD,0,bWaitOnReturn)
Else
Call oAPI.LogScriptEvent(“filecount.exe”, 510, 0, “Can’t find EXE to run Script”)
WScript.Quit
End If
If returnCmd > userCount Then
strReturn = userCount
Call oBag.AddValue(“State”,“BAD”)
Call oBag.AddValue(“ret”,strReturn)
Else
Call oBag.AddValue(“State”,“GOOD”)
End If
Call oAPI.Return(oBag)
To test it I ran this command cscript c:\temp\newtest.vbs “c:\temp” “xml” 4 saying if there are more than 4 files in the directory and should return BAD state and how many files actual files are in the directory. This is what I got back.
<DataItem type=”System.PropertyBagData” time=”2009-06-17T10:58:59.3066298-04:00″
sourceHealthServiceId=”B3B5A38D-0DBE-5CA9-592D-B76333A989D8″>
<Property Name=”State”VariantType=”8″>BAD</Property>
<Property Name=”ret” VariantType=”3″>5</Property></DataItem>
Looks good now to test a good condition. cscript c:\temp\newtest.vbs “c:\temp” “xml” 25 saying if there is more than 25 xml files create an alert. There is not more than 25 files so the scom script should return good.
<DataItem type=”System.PropertyBagData” time=”2009-06-17T10:59:34.5256052-04:00″
sourceHealthServiceId=”B3B5A38D-0DBE-5CA9-592D-B76333A989D8″>
<Property Name=”State” VariantType=”8″>GOOD</Property></DataItem>
Ok now we have a good working script and c# executable. Now we just need to put the script into a monitor and copy the file to the server we want to monitor and we are done. You can follow these directions if you don’t know how to put the script into a monitor. https://www.scom2k7.com/create-a-script-based-unit-monitor-in-opsmgr2007-via-the-gui/
So now think of the possibilities. Anything that can be called from C# can now be monitored in SCOM. SDKs, APIs, Web Services, are all easily leveraged in C#. The only downside is you need the executable on the server the monitor is running on, but that could be fixed by having the script to check for the executable and if it wasn’t there you could copy it from a centralized network location.