Prof. Powershell
Countdown with Timer Object
Now that we know how to set up a timer object, let's get it to do something awesome. Part 2 in a series on the timer object.
- By Jeffery Hicks
- 03/13/2012
Last time we looked at timer objects and how to set them up with an event subscription using the Register-ObjectEvent cmdlet. When the timer reaches 0 the elapsed event fires and PowerShell detects the event. But what we really want is to take some sort of action. Let me show you how.
First, I'll re-create the timer object from last time:
PS C:\> $timer = new-object timers.timer
PS C:\> $timer.interval=10000
PS C:\> $timer.Enabled=$true
Next, we need to define a scriptblock of PowerShell commands. We are going to tie this scriptblock to the subscription so that when the event fires, the code will run. For the sake of demonstration, I'm going to define a new scriptblock that will get the total number of processes and log that information to a text file:
PS C:\> $action={
>> $p=get-process -computer $env:computername
>> $comp=$p[0].Machinename
>> $m="{0} {1} Process count {2}" -f (Get-Date),$comp,$p.count
>> $m | out-file c:\work\log.txt -append
>> }
>>
PS C:\>
This scriptblock will run in a separate PowerShell runspace so it should be as self-contained as possible and not reference anything out of scope. Because this will run "behind the scenes," you should test it first:
PS C:\> Invoke-Command $action
I see the log file is created and the content is as I expect. Now let's hook everything up. We're still going to use Register-ObjectEvent but this time we're going to specify an action:
PS C:\> Register-ObjectEvent -InputObject $Timer -EventName Elapsed -SourceIdentifier ProcessCheck -Action $action
This will create a background job that will execute every time the event fires. We also get an event subscriber object:
PS C:\> Get-EventSubscriber
SubscriptionId : 1
SourceObject : System.Timers.Timer
EventName : Elapsed
SourceIdentifier : ProcessCheck
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : False
ForwardEvent : False
But since the timer is most likely already running, the action is kicking off and my log file is filling up. If for some reason it hasn't started, you can start the timer object:
PS C:\> $timer.start()
Or stop it if you want to make some changes and want to "pause" the event:
PS C:\> $timer.stop()
I recommend stopping the timer before making any changes such as altering the refresh time. Remember this value is in milliseconds:
PS C:\> $timer.Interval=100000
PS C:\> $timer.start()
Because there is an action tied to the event subscription, nothing is written to the event queue so Get-Event comes up empty:
PS C:\> get-event
PS C:\>
All of this will continue running for as long as the timer is enabled and started and your PowerShell session is open. But if you want to clean up and get rid of everything, first disconnect the event subscription"
PS C:\> Unregister-Event ProcessCheck
I specified the name of the event subscription. There is also a stopped job, which really doesn't matter, but if you want to tidy up go ahead and remove it:
PS C:\> Remove-Job -Name Processcheck
Finally, the timer object still exists. This is what I would do:
PS C:\> $timer.stop()
PS C:\> $timer.dispose()
PS C:\> remove-variable timer
Working with timer objects and event subscriptions opens up a wealth of management opportunities, without relying on complicated scheduled tasks. PowerShell 3.0 will introduce some new features that might be even easier to use, but I'll save that for another day.
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.