开发者

How to use .GetNewClosure() with the -Action value for an EngineEvent

& { 
    $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: ".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜