I recently had the need for a function that worked like the WScript.Sleep method in Windows Script Host (WSH) but could wake a script up early if necessary. I was writing a script that had to modify a registry setting and restart a service on 150 servers. I needed a delay between the stopping of the service and the starting of the service. Basically, I wanted to wait until the service stopped before starting it up again.
Unfortunately, the Sleep method is a finite setting, and to the best of my knowledge, you can't wake the script up early. For example, you can't wake up the script if the service stops immediately. I thought about creating a While...Wend statement that uses the InterrogateService method of Windows Management Instrumentation's (WMI's) Win32_Service class to interrogate the service for the status of Service Not Active. However, I realized that if the service's status failed to go to an inactive status, the script would be caught in an endless loop. I needed a function that provided a set time delay as well as checked for the Service Not Active status—whichever event happened first would prompt the script to move on to the next server.
To meet this need, I created the Delay function. The function uses a While...Wend loop to continually check for two conditions:
- Whether the specified time delay (which is passed to the function as a parameter) has elapsed
- Whether a specified second condition (e.g., when a service goes to an inactive status) has been met
If the second condition occurs before the specified time delay has elapsed, the function wakes the script up early, so to speak. (What actually happens is that when one of the conditions is met, the script exits the function, which ends the sleep period.)
As Listing 1 shows, the Delay function first uses VBScript's Now function to set a start point and assigns that value to the MarkTime variable. The Delay function then initializes a counter to zero. Next, a While...Wend loop increments the counter by the number of seconds elapsed between the start time and the current time. To obtain the number of elapsed seconds, the Delay function uses VBScript's DateDiff function to compare the value in the MarkTime variable to the value returned by another execution of the Now function. When the counter equals the number seconds passed as a parameter or when the second condition is met, the function ends.
To call the function, you simply pass the number of seconds as a parameter with code such as
Listing 2 shows how I used the Delay function in one part of my registry script. (This code is for illustration purposes only.) As callout A in Listing 2 shows, I set the time delay for 15 seconds. Callout B shows how the script calls the Delay function into action for each server's service. Callout C highlights the second condition. For this condition, the function uses the Win32_Service class's InterrogateService method to check for the Service Not Active status, which has a value of 6. When the service has an inactive status or when 15 seconds are up, the function ends, thereby waking up the script.
The Delay function proved quite beneficial in my script. If I had used the Sleep function and set the script to sleep for 15 seconds per server, there would have been 37.5 minutes of sleep time (15 X 150/60). The Delay function substantially reduced the sleep time. Because the service typically stopped after about 3 seconds, the script slept for only 3 seconds per server (3 X 150/60), reducing the sleep time to only about 7.5 minutes.