0

I'm writing a PowerShell script in Visual Studio Code which is intended to run a function for every tick of a timer. Here is the code:

$timer = New-Object Timers.Timer
$timer.Interval = 1000
$timer.Enabled = $true

Register-ObjectEvent -InputObject $timer -EventName Elapsed -Action {Write-Host "Tick"}

The problem is that I don't seem to be able to stop the script using Ctrl+C which is what I would normally do, or indeed anything other than actually killing the terminal using the 'dustbin' icon. It just continues printing 'Tick'!

What's going on here? How would I stop this script gracefully?

1
  • Get-EventSubscriber |Unregister-Event Commented Feb 11, 2021 at 13:24

2 Answers 2

1

When you subscribe an action to an event using Register-ObjectEvent, it can be unregistered using the Unregister-Event cmdlet:

$timer = New-Object Timers.Timer
$timer.Interval = 1000
$timer.Enabled = $true

Register-ObjectEvent -SourceIdentifier MyElapsedTick -InputObject $timer -EventName Elapsed -Action {Write-Host "Tick"}

<# ... #>

Unregister-Event -SourceIdentifier MyElapsedTick

To enumerate existing subscribers (for when you forget to specify a SourceIdenfitier for example), use Get-EventSubscriber:

# This will unregister all event subscribers
Get-EventSubscriber |Unregister-Event
Sign up to request clarification or add additional context in comments.

4 Comments

My question is not so much about how to unregister, more how to stop the script. So I need the script to know I'm trying to stop it, so that it can unregister... :)
@David I don't understand what you mean by "stop the script". The script/snippet you posted stops running as soon as Register-ObjectEvent returns, but the event subscription will persist until you unregister (or terminate the process)
Okay, thank you, I understand now. The event registration is independent of the script. So Ctrl+D does stop the script (or would do, if the script hadn't already stopped after calling Register-ObjectEvent, as you say), but the events keep on ticking away.
What I didn't realise from your original post (my fault, not yours) is that I can call Unregister-Event -SourceIdentifier MyElapsedTick outside of the script and it would still work. I assumed that the event registration would be scoped to the script, but that's clearly not the case.
1
$timer = [System.Timers.Timer]::new()
$timer.Interval = 5000
$timer.AutoReset = $false
$timer.Enabled = $true
1..20 | % {
    if (!$timer.Enabled){
        exit
    }
    write-host $_, $timer.Enabled
    Start-Sleep -Milliseconds 1000
}

4 Comments

Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.
I'am russian, i can read in English, but write in English it is hard for me.
@АлексейСеменов, You can always use Google translator or another translator. Your comment is well written.
@АлексейСеменов I very much appreciate your help, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.