How to Schedule Scrips in PowerShell By Using A Timer Object

If you are a Systems Administrator or an enthusiast who used PowerShell scrips, you know they can be very useful. And sometimes you may want to execute a script block at scheduled intervals – for instance, every 10 minutes or every hour. Surely you can set up a task in Windows Task Scheduler that will fire the script off and that works great if it is something you want to run permanently. However, for temporary solutions, such as debugging or monitoring something for a limited period of time, creating a scheduled task becomes extra work. You can avoid it by utilizing a timer to fire off your code at predefined intervals.

If you have dealt with PowerShell scripting but have little understanding of objects, here’s a few words to help you understand. An object can have attributes that describe it, methods that can be called upon the object in order for it to do something, and events that are called when something happens to an object. To give an example, a Person object may have the following attributes: Name, SSN, Sex, Race, Email and the following methods: GoHome, AnswerQuestion, ShakeHand. In this case, it may also have an event: QuestionAsked, which will be called by the system when someone asked our Person object a question and in which case we can call AnswerQuestion in response. Attributes, methods and events that an object has are defined in a class. A class is a generalized definition – you can describe a person using these attributes, and a person can do these actions, and a person can react to these events. Objects are then specific instances of a class.

The class we are interested in for scheduling script blocks is Timers.Timer. First, let’s create an instance (object) of this class:

PS C:\> $Timer = New-Object Timers.Timer

If you would like to see all available attributes, methods and events for the $timer object, you can do it by typing the following command:

PS C:\> $Timer | Get-Member

   TypeName: System.Timers.Timer

Name                      MemberType Definition
----                      ---------- ----------
Disposed                  Event      System.EventHandler Disposed(System.Object, System.EventArgs)
Elapsed                   Event      System.Timers.ElapsedEventHandler Elapsed(System.Object, System.Timers.ElapsedEventArgs)
BeginInit                 Method     System.Void BeginInit()
Close                     Method     System.Void Close()
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose                   Method     System.Void Dispose()
EndInit                   Method     System.Void EndInit()
Equals                    Method     bool Equals(System.Object obj)
GetHashCode               Method     int GetHashCode()
GetLifetimeService        Method     System.Object GetLifetimeService()
GetType                   Method     type GetType()
InitializeLifetimeService Method     System.Object InitializeLifetimeService()
Start                     Method     System.Void Start()
Stop                      Method     System.Void Stop()
ToString                  Method     string ToString()
AutoReset                 Property   System.Boolean AutoReset {get;set;}
Container                 Property   System.ComponentModel.IContainer Container {get;}
Enabled                   Property   System.Boolean Enabled {get;set;}
Interval                  Property   System.Double Interval {get;set;}
Site                      Property   System.ComponentModel.ISite Site {get;set;}
SynchronizingObject       Property   System.ComponentModel.ISynchronizeInvoke SynchronizingObject {get;set;}

I am not going to go into what each of these mean – the ones we are interested in are the Interval and Enabled attributes, the Start and Stop methods and, most importantly, the Elapsed event. After you created the $Timer object you still need to set the interval you want you script block to execute at, as well as enable the timer and actually start it. Let’s start with setting the interval to 5 seconds and enabling it (note that the interval is in milliseconds):

PS C:\> $Timer.Interval = 5000
PS C:\> $Timer.Enabled = $True

And now the fun part – let’s subscribe to the Elapsed event or, in other words, provide a script that should be executed when our timer elapses. Let’s introduce a $Global:Counter that will be incremented every 5 seconds and output to the screen:

PS C:\> $Global:Counter = 0
PS C:\> Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action { $Global:Counter++; Write-Host "Counter is ${Global:Counter}" }

As you can see, there parameters of this command are pretty self-explanatory, with the object we are registering an event for coming first ($Timer), the event we are subscribing to second (Elapsed) and finally, the script block to execute itself. Since the timer is enabled, you will start to see results immediately:

PS C:\> $Timer = New-Object Timers.Timer
PS C:\> $Timer.Interval = 5000
PS C:\> $Timer.Enabled = $True
PS C:\> $Global:Counter = 0
PS C:\> Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action { $Global:Counter++; Write-Host "Counter is
${Global:Counter}" }

Id              Name            State      HasMoreData     Location             Command
--              ----            -----      -----------     --------             -------
1               e4e7dba7-778... NotStarted False                                 $Global:Counter++; Wr...

PS C:\> Counter is 1
Counter is 2
Counter is 3
Counter is 4
Counter is 5
Counter is 6
Counter is 7
PS C:\>

Note that you can call $Timer.Stop() to stop the timer and firing off events. Alternatively, you can also execute $Timer.Enabled = $False.

This entry was posted in PowerShell and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *