& {
$action = & { $y = 100
return { write-host "Value: $y" }.getnewclosure()
}
[void] (register-engineevent -sourcei "foo" -action $action)
[void] (new-event -sourcei "foo")
}
The code above prints Value:, while I开发者_JAVA技巧'd expect it to print Value: 100. Is something missing here?
The engine is calling GetNewClosure() on it, which is a better thing for it to do than not.
When I ran the above, I got an output of only Value:, but then I globally declared $y = 25 and ran [void](new-event -sourcei 'foo') again, the output was Value: 25. Then I changed its value again, $y = 38, and ran the event again: Value: 38.
If what you want is to bake in the value of $y at the time you create the action, one way to do that is to create the scriptblock in such a way that the value of $y becomes a literal or part of a literal:
$action = &{ $y = 100
return (invoke-expression "{write-host 'Value: $y'}")
}
This first parses the string to insert the value, so Invoke-Expression ends up doing the equivalent of this:
{write-host 'Value: 100'}
I'm not sure if there are any other ways to bake in the value other than composing the entire content of the scriptblock in a string and passing it through Invoke-Expression.
In response to your comment, further explanation of closures:
> $action100 = &{$y = 100; return {write-host "Value: $y"}.GetNewClosure()}
> &$action100
Value: 100
That's the result you expect, and that's what you get, because the scriptblock is still "closed" around the value of $y in the scope where GetNewClosure() was called.
> $y = 25
> &$action100
Value: 100
Still closed around the $y that is 100.
> $action25 = $action100.GetNewClosure()
> &$action25
Value: 25
This produces a new scriptblock that encloses variables in the current scope. It makes it re-evaluate what $y is in that scriptblock, and in this context, $y is now 25.
> $y = 38
> &$action100
Value: 100
> &$action25
Value: 25
> &($action100.GetNewClosure())
Value: 38
At this point, because $y is declared globally now, when you call New-Event it will use GetNewClosure() and re-evaluate $y to 38, and print Value: 38. You've been getting Value: because in the context where the engine events call GetNewClosure() the variable $y is not defined, so "Value: $y" becomes "Value: ".
加载中,请稍侯......
精彩评论