New closure on scriptblock
Jobs are executed in a dynamic module; modules have isolated sessionstate, and share access to globals. PowerShell closures only work within the same sessionstate / scope chain. Annoying, yes.
-Oisin
p.s. I say "jobs" because event handlers are effectively local jobs, no different than script being run with start-job (local machine only, implicit, not using -computer localhost)
I think you are making assumptions that don't hold. PSH is interpreted, so when a code block is created it just holds the source code. When it is later evaluated any variables it uses will be looked up in the normal PSH way: first in the current scope, and then in each outer scope until a variable with a matching name if found.
When the timer fires its event, it executes the code block and thus looks up $i
. Which is found in the outer scope with a value of 2.
In the second case, if you just use the code block directly (remove call to GetNewClosure
) then the second execution gives 2.
Use global variables in that case:
PS> $global:i = 1PS> $timer = New-Object Timers.TimerPS> $timer.Interval = 1000PS> Register-ObjectEvent $timer Elapsed -Action { write-host 'i: ' $global:i }.GetNewClosure()PS> $timer.Enabled = 1i: 1i: 1i: 1PS> Set-Variable -Name i -Value 2 -Scope Globali: 2i: 2i: 2
Source:
http://stackoverflow.com/q/12535419/1287856