Prof. Powershell

Perfect Timing with New-Object

Create a timer object with PowerShell New-Object cmdlet to schedule recurring tasks at intervals.

You may have scenarios where you want to execute some PowerShell code at repeated intervals. One way to accomplish this would be to go through the effort of creating a scheduled task to run a PowerShell script or command. There's nothing wrong with this approach, but sometimes it is a lot of work, especially if you only need a temporary solution. Let me show you an alternative with a special type of object and event subscriptions.

In Windows, things happen all the time: services start, processes terminate, files are closed etc. When one of these predefined actions, or events, occurs, it is said to have "fired." In Windows programming we can create special objects to listen for these events, called event subscribers. We can also use Windows PowerShell and it doesn't require any programming skills.

In the scenario I outlined at the beginning, the type of object we want to subscribe to is a timer object, which we can easily create with the New-Object cmdlet:

PS C:\> $timer = new-object timers.timer

Here's what we created:

PS C:\> $timer

AutoReset           : True
Enabled             : False
Interval            : 100
Site                :
SynchronizingObject :
Container           :

The key properties are Enabled and Interval. The former should be self-explanatory. The latter is the number of milliseconds that the timer will count down. The default is 100. When the timer reaches zero, it will start counting down again. You can control that behavior with the AutoReset property. I'll go ahead and set a few values:

PS C:\> $timer.interval=10000
PS C:\> $timer.Enabled=$true

The timer will now count down every 10 seconds and it is ready to go, although we haven't started it yet. Before we go any further, let's look more closely at this object.

PS C:\> $timer | get-member

TypeName: System.Timers.Timer

Name                      MemberType Definition
----                      ---------- ----------
Disposed                  Event      System.EventHandler Disposed(System.Obj...
Elapsed                   Event      System.Timers.ElapsedEventHandler Elaps...
BeginInit                 Method     System.Void BeginInit()
Close                     Method     System.Void Close()
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateOb...
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 Contai...
Enabled                   Property   System.Boolean Enabled {get;set;}
Interval                  Property   System.Double Interval {get;set;}
Site                      Property   System.ComponentModel.ISite Site {get;s...
SynchronizingObject       Property   System.ComponentModel.ISynchronizeInvok...

Notice the events at the beginning? These are things we can subscribe to. To do that we will need to create an event subscription using the Register-ObjectEvent cmdlet:

PS C:\> Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier Test

The event name is what we're watching for. When the timer reaches zero the Elapsed event fires, and we'll be notified. It is a good idea to include a SourceIdentifier to name the subscription. Finally, in order for this to do anything we need to start the timer object.

PS C:\> $timer.start()

Now that it is running let's quickly look at what we created when we registered for the event.

PS C:\> Get-EventSubscriber

SubscriptionId   : 1
SourceObject     : System.Timers.Timer
EventName        : Elapsed
SourceIdentifier : Test
Action           :
HandlerDelegate  :
SupportEvent     : False
ForwardEvent     : False

If you have a many event subscriptions using SourceIdentifier really comes in handy. At this point probably at least 10 seconds have expired so let's see if anything was detected. We'll use the Get-Event cmdlet.

PS C:\> get-event | select –first 2

ComputerName     :
RunspaceId       : afed5fc4-0309-4d82-8beb-b50c5c4cf787
EventIdentifier  : 1
Sender           : System.Timers.Timer
SourceEventArgs  : System.Timers.ElapsedEventArgs
SourceArgs       : {System.Timers.Timer, System.Timers.ElapsedEventArgs}
SourceIdentifier : Test
TimeGenerated    : 2/2/2012 5:01:10 PM
MessageData      :

ComputerName     :
RunspaceId       : afed5fc4-0309-4d82-8beb-b50c5c4cf787
EventIdentifier  : 2
Sender           : System.Timers.Timer
SourceEventArgs  : System.Timers.ElapsedEventArgs
SourceArgs       : {System.Timers.Timer, System.Timers.ElapsedEventArgs}
SourceIdentifier : Test
TimeGenerated    : 2/2/2012 5:01:20 PM
MessageData      :

You can see from TimeGenerated that these are 10 seconds apart. The timer will continue to generate events until I exit PowerShell, get rid of the subscription (I'll cover that next time) or simply stop the timer.

PS C:\> $timer.stop

If I later restart the timer, I'll continue to get event notifications for as long as I have a subscriber. That's all I have time for this time, but hopefully you've grasped the fundamental concepts. Next time, I'll show you how to hook up an action to this event.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular