Archive for the ‘scripting’ Category

Using Nagios NRPE To Monitor Windows User Accounts Via WMI…….

Wednesday, February 8th, 2012

My last post on the subject of using the Nagios NRPE plugin to monitor stuff on Windows. This time I want to be monitor some Window domain user accounts for lockout status.

We run some of our windows services using ordinary domain user accounts instead of the built in local service accounts. This is normally when the service in question needs to read or write to network shares on another server, the built in service accounts don’t seem to pass and username/password along with the request and so the connection fails. When you run the process under a domain account, the name and password are passed along with the connection request and as long as you have set your share and NFS permissions correctly it should work.

We recently had an application stop working and it turned out to be that the domain user account that the service ran under had become locked out.

So I decided it would be a good idea to get a heads up about this sort of thing sooner rather than later. The script needs to run on your AD domain controllers (x1 is probably fine as they all replicate user data, but more might allow detection a little quicker).

The code for the script is below.

' account name supplied as argument
strAccount = Wscript.Arguments.Item(0)

' bind to the MERCURY domain
Set objComputer = GetObject("WinNT://MYDOMAIN")

objComputer.Filter = Array("User")
' for each service compare it’s display name to the current one we are looking for
For each objUser in objComputer
    If objUser.Name = strAccount then
    	If ObjUser.IsAccountLocked <> 0 then
    		Wscript.echo "Account is locked out"
    		Wscript.Quit (2)
    	Else
    		Wscript.echo "Account is ok"
    		Wscript.Quit (0)
    	End if
    End if
Next

The script is using WMI to check the IsAccountLocked value of a user object. The user object has quite a lot of key pair values that you can monitor, basically all the fields and check boxes you see in the AD user dialogue box.

In this instance, I am only interested in the ‘Account is locked out’ check box. If it’s checked the value will be something other than 0 (1 in this case)and I want an alert, but if the value is still 0 then it’s not checked and the account is ok.

As with the prior checks I wrote about, the .vbs script file needs to be dropped into the ‘libexec’ folder, and a line like below needs to be added to the nrpe.cfg config file on the windows server.

command[check_windows_account]=cscript.exe //T:30 //NoLogo "C:\Program Files (x86)\NRPE_NT\libexec\check_windows_account.vbs" "$ARG1$"

On the Nagios server you need to add a command definition to the commands.cfg file.

# 'check_windows_account' command definition (using nrpe)
define command{
        command_name    check_windows_account
        command_line    $USER1$/check_nrpe -H $HOSTADDRESS$ -t 60 -p 5666 -c check_windows_account -a $ARG1$
}

And finally a service check has to be created in the services.cfg file and a server to be checked needs to be added (in this example I’m checking the account ‘AppUser’ on the server Windows_Server_1.

define service{
        service_description     Check Windows User Account
        servicegroups           cust-windows
        host_name               windows_server_1
        check_command           check_windows_account!"AppUser"
        use                     generic-service
}

Hopefully these scripts have given you an idea of what you can do with the NRPE plugin. As long as you can write a script to check a known value of something, you can get Nagios to use it as a monitor and fire an alert. And it doesn’t have to be VBScript, Powershell, Perl, Python they all can be used. You can monitor WMI objects, or Windows Perfmon Counters, the list is vast.

Enjoy ;oD

Using Nagios NRPE To Monitor Windows Processes Via WMI…….

Tuesday, February 7th, 2012

Hot on the heels (well ok, Oct last year to be precise) of Using Nagios NRPE To Monitor Windows Services Via WMI comes Using Nagios NRPE To Monitor Windows Processes Via WMI.

Naturally, after providing work with a Nagios check to tell us when a named Windows service was not in a running state, the next question from their mouths was going to be


“can Nagios tell us when a program that is not a service has stopped running ?”

Well yes it can, and it’s not difficult. Instead of looking at the list of services, we need to read the list of processes running (like the list you can see in Task Manager) and look to see if our one is included in the list.

Task Manager Process List

The code to do this is below.

strComputer = "."
'list services to monitor, comma seperated, inside quotes
strProcess = Wscript.Arguments.Item(0)
'connect using standard monkier
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
'search for our process
Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '" & strProcess & "'")
If colProcesses.Count > 0 Then
'If the process is running return exit code 0 = ok
	Wscript.Echo "SERVICE STATUS: OK"
	Wscript.Quit(0)
Else
	'otherwise return non 0 = error = fire alert hopefully
	Wscript.Echo "SERVICE STATUS: Critical"
	Wscript.Quit(2)
End If

Again, the walk through of this is quite simple. We call the program with x1 parameter/argument, a string containing the name of the process we are looking for (NOTE: this needs to be the full name including the ‘.exe’ or ‘.com’ and if it contains space characters the whole thing should be enclosed in quote marks).

We then bind to WMI and run a query to find our process in the list of running processes. The last part simply counts how many results were returned. If the count is larger than 0, the process must be running and we return a status code 0 for success, if not, we return a status code of 2 and Nagios fires a critical alert (if you prefer a warning rather than a critical then adjust to return a 1)

Note: The string search is not case sensitive, ‘OUTLOOK.EXE’ and ‘outlook.exe’ equate the same regardless of how the process actually looks in the list.

As with the previous check, the .vbs script file needs to be dropped into the ‘libexec’ folder, and a line like below needs to be added to the nrpe.cfg config file on the windows server.

command[check_windows_process]=cscript.exe //T:30 //NoLogo "C:\Program Files (x86)\NRPE_NT\libexec\check_windows_process.vbs" "$ARG1$"

On the Nagios server you need to add a command definition to the commands.cfg file.

# 'check_windows_process' command definition (using nrpe)
define command{
        command_name    check_windows_process
        command_line    $USER1$/check_nrpe -H $HOSTADDRESS$ -t 60 -p 5666 -c check_windows_process -a $ARG1$
}

And finally a service check has to be created in the services.cfg file and a server to be checked needs to be added (in this example I’m checking for ‘outlook.exe’ on the server Windows_Server_1.

define service{
        service_description     Check Windows Process
        servicegroups           cust-windows
        host_name               windows_server_1
        check_command           check_windows_service!"outlook.exe"
        use                     generic-service
}

The current script simply alerts if a process is found to be missing from the task list, but it could be modified. You could have it fire a warning if the number of processes is more than 5 but less than 10, and a critical is the number drops below 5 for example.

Using Nagios NRPE To Monitor Windows Services Via WMI Part 2…….

Friday, September 30th, 2011

Have realised my first attempt at using NRPE to monitor Windows services via WMI is in fact badly thought out and badly done. This is what happens when companies want everything yesterday and rush things :o(

Having thought about it, the following has come to mind:

The service string to check should not be hard coded into the script. Otherwise we would need x1 script per service to check (i.e. lots !). The service string should be a variable that we can pass to the script as an argument at run time.

And, we can only check one service at a time with this script. Therefore, placing the service name into an array is whaaaayyy overkill. Will simply replace the array with a single string variable.

This in mind, here’s the revised version of the check script

strComputer = "."
'list services to monitor, comma seperated, inside quotes
strService = Wscript.Arguments.Item(0)
'connect using standard monkier
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
'get an array containing all services
Set objItems = objWMIService.ExecQuery ("Select * from Win32_Service")
'for each service compare it’s display name to the current one we are looking for
For each objService in ObjItems
	'if we get a service display name match
	If objService.DisplayName = strService Then
		'display the current service along with it’s current state
		'wscript.echo "service name = " & objService.DisplayName & " currently :: " & objService.State
		If objService.State = "Running" Then
		'If the service is running return exit code 0 = ok
			Wscript.Echo "SERVICE STATUS: OK"
			Wscript.Quit(0)
		Else
		'otherwise return non 0 = error = fire alert hopefully
			Wscript.Echo "SERVICE STATUS: Critical"
			Wscript.Quit(2)
		End if
	End if
Next

And the command to add to the nrpe.cfg file will now need a parameter adding to the end like so (note the quote marks “” around the $ARG1$ parameter. This is in case our variable has spaces in it !!).

command[check_windows_service]=cscript.exe //T:30 //NoLogo "C:\Program Files (x86)\NRPE_NT\libexec\check_windows_service.vbs" "$ARG1$"

The command.cfg file will need a command definition in it like this

# 'check_windows_service' command definition (using NRPE)
define command{
	command_name	check_windows_service
	command_line	$USER1$/check_nrpe -H $HOSTADDRESS$ -t 60 -p 5666 -c check_windows_service -a $ARG1$
}

And finally, in services.cfg, a service check section using the command, like this

define service{
        service_description     Check Windows Awesome Service
        servicegroups           cust-windows
        host_name               windows_server_1
        check_command           check_windows_service!"Some Windows Service"
        use                     generic-service
}

But we can now use the same script to check other services like this

define service{
        service_description     Check Windows Awesome Service
        servicegroups           cust-windows
        host_name               windows_server_1
        check_command           check_windows_service!"Some Windows Service"
        use                     generic-service
}

define service{
        service_description     Check Windows Spooler Service
        servicegroups           cust-windows
        host_name               windows_server_1
        check_command           check_windows_service!"Print Spooler"
        use                     generic-service
}

Second time’s a charm. At least I got to go back and correct my horrible (but technically working) mistake !

Next stop, monitoring for running processes by their executable name in the process list…….

doh !

Using Nagios NRPE To Monitor Windows Services Via WMI…….

Wednesday, September 28th, 2011

If you are setting up Nagios from scratch, install the NSClient++ agent on your Windows servers and get the increased flexibility that it offers. My predecessor at my current work place has only installed the NRPE addon (the same guy who installed the core datacentre router with a duplex mismatch….that made my first week fun), which means I can’t use much of the cool check_nt stuff to monitor services and processes :o(

I needed a way to tell if a service had stopped on Windows server, but I could only use NRPE. First stop, a script to check the status of a given service.


strComputer = "."
'list services to monitor, comma seperated, inside quotes
arrServices = Array("Awesome Service")
For each strService in arrServices
	'connect using standard monkier
	Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	'get an array containing all services
	Set objItems = objWMIService.ExecQuery ("Select * from Win32_Service")
	'for each service compare it’s display name to the current one we are looking for
	For each objService in ObjItems
		'if we get a service display name match
		If objService.DisplayName = strService Then
			'display the current service along with it’s current state
			'wscript.echo "service name = " & objService.DisplayName & " currently :: " & objService.State
			If objService.State = "Running" Then
			'If the service is running say so
				Wscript.Echo "SERVICE running"
			Else
			'otherwise it must not be runing
				Wscript.Echo "SERVICE not running"
			End if
		End if
	Next
Next

This script binds to WMI, searches for a service called Awesome Service and then echoes a statement to say if it’s running or not. Perfect, but Nagios can’t use this quite yet. We need the script to send some data back to the NRPE engine for this to work.

The Nagios plug-in dev guide tells you most of what you need to know, in this case we need to pass return codes back, which is covered here.

So the finished version now looks like this


strComputer = "."
'list services to monitor, comma seperated, inside quotes
arrServices = Array("Awesome Service")
For each strService in arrServices
	'connect using standard monkier
	Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	'get an array containing all services
	Set objItems = objWMIService.ExecQuery ("Select * from Win32_Service")
	'for each service compare it’s display name to the current one we are looking for
	For each objService in ObjItems
		'if we get a service display name match
		If objService.DisplayName = strService Then
			'display the current service along with it’s current state
			'wscript.echo "service name = " & objService.DisplayName & " currently :: " & objService.State
			If objService.State = "Running" Then
			'If the service is running return exit code 0 = ok
				Wscript.Echo "SERVICE STATUS: OK"
				Wscript.Quit(0)
			Else
			'otherwise return non 0 = error = fire alert hopefully
				Wscript.Echo "SERVICE STATUS: Critical"
				Wscript.Quit(2)
			End if
		End if
	Next
Next

So if the service is running, we exit with return code 0 Wscript.Quit(0). But if it’s not, we exit with a non 0 return code. I need an alert to fire an SMS, so I have used Wscript.Quit(2) for critical, but if you only want a warning you can use Wscript.Quit(1).

Save the file in the NRPE scripts location (mine are located at C:\Program Files\NRPE_NT\libexec\

Final piece of the puzzle is to add the actual command to run the script to the NRPE config file. Mine is located at ‘C:\Program Files\NRPE_NT\bin\nrpe.cfg’, but your may vary.

At the end of the file are a list of demo commands, we just need to add in


command[check_awesome_service]=cscript.exe //T:30 //NoLogo "C:\Program Files\NRPE_NT\libexec\check_awesome_service.vbs"

Now add a command definition to the Nagios commands.cfg


# 'check_awesome_service' command definition (using nrpe)
define command{
        command_name    check_galaxy_service
        command_line    $USER1$/check_nrpe -H $HOSTADDRESS$ -t 60 -p 5666 -c check_awesome_service
        }

And finally in my Nagios services.cfg file an service definition that includes the command and the hosts to run this against


define service{
        host_name               windows_server_1
        service_description     Windows Awesome Service
        servicegroups           cust-windows
        check_command           check_awesome_service
        use                     generic-service
}

And that should be it. You need to restart Nagios to include the new commands and service definitions. And then test the monitor by stopping and the starting the service in question.

The next step would be to replace the service name in the .vbs script file with a variable. Then you can reuse the same script to monitor different services by passing the service name from Nagios to NRPE as a variable from the config file. :oD

Recursive Grep For Solaris…….

Thursday, August 11th, 2011

Solaris doesn’t seem to have a ‘-r’ switch to perform recursive string searches (at least not on version 10 on Intel x86 anyway)

:o(

The following works as a workaround/substitution


find -type f | xargs grep -i

 

That is all……..

 

Powershell Create DNS Sub Domain…….

Friday, August 5th, 2011

I’ve been working on some Software as Service systems for the last few weeks. They offer a basic fixed configuration of our applications for a smaller price, but are not as customisable as a dedicated full application system.

Being of a fixed configuration means of course that admin process for creating instances was just ripe for scripting and automating. As the system was running on Windows server 2008R2, I decided to use Powershell as it would enable me to work with DNS, filesystem and IIS.

The first part of the process was to create internal DNS records. The platform requires x3 DNS records creating, x1 A record and x2 CNAME. The A record should be blank so it points to the sub domain itself and thereby assigns it an IP address. The CNAMEs should be ‘live’ and ‘preview’ and should point to te afore mentioned A record (they all come from the same IIS server and use host headers, so only the x1 IP address is needed)

The system main DNS namespace domain being ‘company.com’, each client should have the domain ‘client.company.com’ with the actual records created inside this sub domain. So the order of actions to my mind was

1) Create sub domain
2) Create A record in sub domain
3) Create x2 CNAME records in sub domain that point to the A record

First task, create the sub domain. Powershell command to do this ?

([WMIClass]"\\sandpit\root\MicrosoftDNS:MicrosoftDNS_Zone").CreateZone("subcompany.company.com", 0, $False)

Now previously when I had done this via the DNS admin GUI, the results looked something like this

However, what I got instead was this

While technically correct, a little untidy to look at. The command created the DNS subdomain folder as the same folder level of the parent DNS domain folder, and then created a delegated zone inside the main DNS domain folder (little greyed out bugger !)

Spent a little while trying various things, googling etc. etc. and got no-where. Decided to move and and proceed with the next part, to create actual host records. Again, powershell script for this was

([WMIClass]"\\sandpit\root\MicrosoftDNS:MicrosoftDNS_AType").CreateInstanceFromPropertyData(sandpit, company.com, subcompany.company.com, 1, 3600, 192.168.4.58)

The arguments in parenthesis can be explained here, but what came as a pleasant surprise was thay when I looked in the DNS admin console to check the details of teh A record I had just created, it appeared as shown below

Yup, it seems that the script, much like the admin console, will create any missing/required domain/subdomain folders necessary to hold DNS records that you try to create !

And they say there’s no such thing as a free lunch.

Powershell Log File Zipper…….

Wednesday, June 23rd, 2010

Another annoying repetitive task automated ! Ahhhhhhh :o)

The log files for our IIS servers build up over a couple of months and consume disk space to the point of becoming an issue. I had been manually logging on and creating a .zip file for each month and then dragging the individual files into the zip file.

Tedious and repetitive, just the sort of thing scripting was made for. Typicaly my scripts for Windows are in vbscript, but this time I decided it was time to look at powershell.

The logic was simple enough. First create a zip file for the previous month. The logfile names are in the format ‘u_ex.log’ where mm is the numerical month. I needed to get the current month, subtract one (compressing previous months logs) and then move any file with a mm figure that matched into the .zip file.

I found this article for creating the actual zip file itself. Then is was just a case of setting the paths and looping through each file in the directory (get-childitem makes this a breeze).

Debugging the script was a bit of a pain in the arse using the built in Windows tools, so I downloaded and installed PowerShell GUI from here. It’s still a work in progress in some respects, the built in intellisense isn’t 100% there just yet, but it does allow you to step through code and what the vaule of your variables and figure out what is happening.

Once I had the script working of the command line, it was just a case of scheduling the job to run on the 1st day of each month recurring. However, this proved to be almost as big a task as the script itself.

For some reason, running powershell.exe and passing the script to it as an argument, ever using the full -command “$ syntax failed to execute the script. In the end I had to create a batch/.cmd file and place the powershell command in there and schedule the batch file to run instead.

My only gripe is that the command to move the file into the zip file is asynchronus so I had to include a sleep/wait period to give the file time to be compressed before being moved into the .zip file. That being said, there will never be more the x31 files, and allowing x2 mins for each file to compress (extremely generous) means the script should never take more than x1 hour to complete, so as long as I run it during a quiet period it should not impact anything else.

I eagerly await the 1st of July to see if the scheduled job kicks in automatically on the live evironment……:o/

#declare functions here
function new-zipfile {
	param ($zipfile)
	if (! $zipfile.endswith('.zip')) {$zipfile += '.zip'}
	set-content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
	(dir $zipfile).IsReadOnly = $false
}

#define variables here
#some strings and numbers we will need
$thismonthint = get-date -f "MM"
$prevmonthint = (get-date).addmonths(-1).tostring("MM")

$thismonthstr = get-date -f "MMM"
$prevmonthstr = (get-date).addmonths(-1).tostring("MMM")

$thisyearlongint = get-date -f "yyyy"
$thisyearshortint = get-date -f "yy"

$thislogdir = 'C:\weblogs\'
$thiszipfile = $thislogdir + $prevmonthstr + $thisyearlongint + '.zip'
$zipexists = test-path $thiszipfile

#start program here
#first pass, check for .zip files of previous months. if exists exit. if not exist, create empty .zip file
if (! $zipexists)
{
	echo 'zip file does not exist, creating zip file'
	new-zipfile $thiszipfile
}
else
{
	return
}

# move all log files where the month number matches the month number of the .zip file
# Jan = 01, Feb = 02, Mar =03 etc. etc.

foreach ($file in Get-ChildItem $thislogdir)
{
	# exclude the .zip files already in the directory (just in case we get a random month match in their filename
	if (! $file.name.endswith(".zip"))
	{
		# if the
		if ($file.Name.substring(6,2) -match $prevmonthint)
		{
			$zipfile = (New-Object -ComObject shell.application).NameSpace($thiszipfile)
			$zipfile.MoveHere($file.fullname)
			Start-Sleep -Seconds 120
		}
	}
}

squish !!

WMI Restart Windows Services

Wednesday, June 10th, 2009

Ok

So the title for this post isn’t smart or quippy. and there is a very good reason for this. I needed a script that could restart a windows service or services. I couldn’t find any good ones :o(

I searched using various combinations of the words “wmi, windows, services, restart, start, stop”. While I found a lots of scripts, they all lacked a certain resiliancy that I like in my automation solutions. Essentially they all went something like this (the wmi has been translated into an english procedure so everyone can understand)

  • connect to windows using wmi
  • find all the services
  • select the one that we are interested in using a for/next loop
  • send it a stop signal
  • wait for some random amount of time (between 1 and 2 mins say !)
  • send the same service a start signal
  • move on to the next service
  • exit the script when we have restarted all the services we want to do

Anyone see the problem ? How long do you give a windows service to stop sucessfully ?  Or start for that matter ! These scripts all seemed to wait for a minute or two, and then procede with the assumption everything happend ok. At some point, that kind of thinking with software will bite you in the ass. Here was what I was looking for

  • connect to windows using wmi
  • find all the services
  • select the one that we are interested in
  • check it current state (running or stopped)if the service is stopped, send it a start signal
  • check every 10 seconds for 5 mins that the status has switched to running
  • if the service does not go into a running state after mins, email an smtp address advising the service is misbehaving and then exit the script
  • if the service is already in a running state, send it a stop signal
  • check every 10 seconds for 5 mins that the status has switched to stopped
  • if the service does not go into a stopped state after mins, email an smtp address advising the service is misbehaving and then exit the script
  • if the service does go into a stopped state within 5 mins, run the section of code for starting a service
  • again, monitor the servce to make sure it does restart, if not for any reason, send a warning email

Using this method no assumptions are made about the running state of the service, or it’s response to being told to stop/start. Worst case scenario, it fails to do what it is told and you get an email warning you the you need to intervene manually, at least the failure is known about and can be managed.

The code for this is shown below. Feel free to copy and adapt to suit your own purpose(s) :oD

'needs be run with administrator privileges in oder to work ! we are doing stuff to services after all !!
'the script gives each service x5 mins to change it's state. if this had not occured within that time
'the script sends a failure email and exits

'define the computer name and the services we want to restart. use "." for local host
'the service names are based on their display names, not their short form/function names !
'define the counter used to determin when 5 mins has elapsed
strComputer = "."
arrServices = Array("Kaspersky Administration Server", "Kaspersky Anti-Virus", "Kaspersky Anti-Virus Script Interceptor Dispatcher", "Kaspersky Lab Cisco NAC Posture Validation Server", "Kaspersky Network Agent")
Dim Count

'loop through each service
For each strService in arrServices
	'connect using standard monkier
	Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	'get an array containing all services
	Set objItems = objWMIService.ExecQuery ("Select * from Win32_Service")
	'for each service compare it's display name to the current one we are looking for
	For each objService in ObjItems
		'if we get a service display name match
		If objService.DisplayName = strService Then
			'display the current service along with it's current state
			wscript.echo "service name = " & objService.DisplayName & " currently :: " & objService.State
			'if it is currently running, attempt to stop it
			If objService.State = "Running" Then
				wscript.echo ""
				wscript.echo "stopping service..."
				wscript.echo ""
				objService.StopService()
				'wait for 10 seconds, then refresh our view of the current object state
				wscript.sleep 10000
				objService.Refresh_
				'if the service is still not in a stopped state, repeatedly re-check the object status every 10 seconds
				'we also check how many times we have already cheked and exit is it is greater than 29 (30*10seconds = 5mins)
				'initialise counter
				Count = 1
				'start checking comparison loop for 'stopped' condition
				'we need to update the objService.State view using objService.Refresh_ for each iteration to make sure we are seeing the
				'current state of the service
				While objService.State <> "Stopped"
					objService.Refresh_
					'for testing/debuging on the console, tell the user what is going on
					'this will not show up when the script is run as a scheduled job
					wscript.echo ""
					wscript.echo "waiting for service to Stop :: current count = " & Count
					wscript.echo ""
					'wait 10 seconds then increase the counter by 1
					wscript.sleep 10000
					Count = Count + 1
					'if we have reached 30 attempts then bow out and send an email advising manual intervention
					If Count > 29 then
						SendFailedMsg
						wscript.echo "service has taken too long to respond. aborting script"
						wscript.quit
					Else
					End if
					'otherwise we have not reached 30, go round again
				Wend
				'once the service has stopped, let us know
				wscript.echo "service is now " & objService.State
				'now attempt to restart the service, making sure it is definateley stopped first
				If objService.State = "Stopped" Then
				wscript.echo ""
				wscript.echo "attempting to restart service " & objService.DisplayName
				wscript.echo ""
				objService.StartService()
				'wait 10 seconds, the refresh our view of the current object state
				wscript.sleep 10000
				objService.Refresh_
				'if the service is not in a running state, repeatedly re-check the object status every 10 seconds
				'we also check how many times we have already cheked and exit is it is greater than 29 (30*10seconds = 5mins)
				'initialise counter
				Count = 1
				'start checking comparison loop for 'running' condition
				'we need to update the objService.State view using objService.Refresh_ for each iteration to make sure we are seeing the
				'current state of the service
				While objService.State <> "Running"
					objService.Refresh_
					'for testing/debuging on the console, tell the user what is going on
					'this will not show up when the script is run as a scheduled job
					wscript.echo ""
					wscript.echo "waiting for service to Start"
					wscript.echo ""
					'wait 10 seconds then increase the counter by 1
					wscript.sleep 10000
					Count = Count + 1
					'if we have reached 30 attempts then bow out and send an email advising manual intervention
					If Count > 29 then
					SendFailedMsg
					wscript.echo "service has taken too long to respond. aborting script"
					wscript.quit
					Else
					End if
					'otherwise we have not reached 30, go round again
				Wend
				'once the service has started, let us know
				wscript.echo ""
				wscript.echo "service is now " & objService.State
			Else
				'otherwise, if the service must already stopped for some reason ? check first, and attempt to start it
				If objService.State = "Stopped" Then
					wscript.echo ""
					wscript.echo "attempting to restart service " & objService.DisplayName
					wscript.echo ""
					objService.StartService()
					'wait 10 seconds, the refresh our view of the current object state
					wscript.sleep 10000
					objService.Refresh_
					'if the service is not in a running state, repeatedly re-check the object status every 10 seconds
					'we also check how many times we have already cheked and exit is it is greater than 29 (30*10seconds = 5mins)
					'initialise counter
					Count = 1
					'start checking comparison loop for 'running' condition
					'we need to update the objService.State view using objService.Refresh_ for each iteration to make sure we are seeing the
					'current state of the service
					While objService.State <> "Running"
						objService.Refresh_
						'for testing/debuging on the console, tell the user what is going on
						'this will not show up when the script is run as a scheduled job
						wscript.echo ""
						wscript.echo "waiting for service to Start"
						wscript.echo ""
						'wait 10 seconds then increase the counter by 1
						wscript.sleep 10000
						Count = Count + 1
						'if we have reached 30 attempts then bow out and send an email advising manual intervention
						If Count > 29 then
						SendFailedMsg
						wscript.echo "service has taken too long to respond. aborting script"
						wscript.quit
						Else
						End if
						'otherwise we have not reached 30, go round again
					Wend
					'once the service has started, let us know
					wscript.echo "service is now " & objService.State
					wscript.echo ""
					End If
				End If
			End If
		End If
	Next
Next

SendSucessMsg

Sub SendFailedMsg()
    Set objEmail = CreateObject("CDO.Message")
    objEmail.From = "email@yourcompany.com"
    objEmail.To = "email@yourcompany.com"
    objEmail.Subject = "KAV Recycle failed on objEmail.Textbody = "KAV services recycle failed on . Please check services manually"
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "yourmailserver.company.com"
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
    objEmail.Configuration.Fields.Update
    objEmail.Send
End Sub

Sub SendSucessMsg()
    Set objEmail = CreateObject("CDO.Message")
    objEmail.From = "email@yourcompany.com"
    objEmail.To = "email@yourcompany.com"
    objEmail.Subject = "KAV Recycle suceeded on . Hooray !!"
    objEmail.Textbody = "KAV services recycle completed OK on :o)"
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "yourmailserver.company.com"
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
    objEmail.Configuration.Fields.Update
    objEmail.Send
End Sub

Once I got this script to run in an admin enabled DOS prompt window, the next step was to run it as a job via the job scheduler under windows. You need to run the job as the SYSTEM user, and tick the box to ‘run with highest available permissions’ in order for this to work. Running as a scheduled job, there is no console to display the output for the job, but you can have the services panel loaded and keep refreshing the view to see your services status changing as the script runs through them.

Overall result will be you get an email advising of a sucessful recycle of your services, or a failure one with a note to check what’s going on.

Enjoy :oD

Rule Of Thumb

Saturday, May 23rd, 2009

We use email as part of the monitoring solutions at work. There are always a few dozen alerts issued during the working day (sometime considerably more if we have a problem…..or sometimes just a problem with the monitoring system itself :o)

To keep some sot of order on my inbox, I have created sets of rules that either move, delete or do some other action with msgs that are pushed onto me. During the working day this is all automatic and working fine.

However, out of hours presents a slight issue. we use Blackberry devices to stay in touch with our email boxes during the evenings so that we receive the email alerts from the monitoring system. A Blackberry enterprise server (BES) sits adjacent to the exchange server and watches the inbox of certain people. If a new message hits the inbox, the BES will push a copy of the email out to the blackberry mobile device. But here’s the problem, if my rules are left running active, the messages get sorted before they actually hit the inbox…….so the BES never sees them and I don’t get a copy sent to me :o(

The work around for this is pretty simple, I just deactive my rules when I leave the office at night. This does sometimes however result in my arriving to an inbox *full* with unsorted alert messages. To clear my inbox down, I have to manually run my rule sets aginst my inbox, and for the number of rules I have that’s a lot of clicking for first thing in the morning.

So I thought I would have a look at automating this task with the built in office visual basic. My first stumbling block here is pretty big. I am not a programmer/coder by any stretch of the imagination. All other office applications will allow you to get the bones of a macro down by recording your actions in the application. The vba editor then presents you with the code for the actions you just carried out, and you can flesh the code out a bit to make it more slightly more generic and vastly more useful.

Outlook does not have this recording feature :o( so, you have to start pretty much from a blank slate. The office installed help file are however incredibly useful and concicse and following them I was able lash the following together

Sub runrules()
Dim colRules As Outlook.Rules
Dim oRule As Outlook.Rule
Dim oInbox As Outlook.Folder
Set oInbox = Application.Session.GetDefaultFolder(olFolderInbox)
Set colRules = Application.Session.DefaultStore.GetRules
For Each oRule In colRules
oRule.Execute showprogress:=True
Next
End Sub

It’s pretty short, not terribly verbose and contains no error checking, but it does do the trick (it was more verbose while I was working it out, I had msgboxes popping at various stages informing me what certain objects and their values were)

I think I’m gonna share this with my boss as he has even more inbox mail rules than I do :oO

Score those brownie points !