A script block is bound to a SessionState immediately if you use the { ... } syntax, or upon the first invocation if the script block was created some other way, e.g. [ScriptBlock]::Create(). The binding is to the active SessionState.
Indeed that seems to be correct. This thread contemplates that behavior extensively. For reference, here is an annotated example exercising the interactions between PowerShell scopes, . and &, modules, and SessionStates.
Consider the following code in which two instances of identical scriptblocks produced by [scriptblock]::Create() are invoked using the call operator & and SteppablePipeline, respectively:
function Invoke-Call {
[CmdletBinding()]
param(
[scriptblock]
$ScriptBlock,
$a
)
& ([scriptblock]::Create({ param ($sb,$__a) . $sb $__a })) <# This scriptblock gets bound to the SessionState that is active when the call operator is invoked. #> `
$ScriptBlock $a
}
function Invoke-Steppable {
[CmdletBinding()]
param(
[scriptblock]
$ScriptBlock,
$a
)
$pipe = [scriptblock]::Create({ param ($sb,$__a) . $sb $__a }). # To what SessionState does this scriptblock get bound?
GetSteppablePipeline(
$MyInvocation.CommandOrigin,
@($ScriptBlock,$a))
$pipe.Begin($PSCmdlet)
$pipe.End()
}
Invoke-Call -a 'c' -ScriptBlock { param($x) [pscustomobject]@{function = 'Invoke-Call'; x=$x; a=$a; __a=$__a }}
Invoke-Steppable -a 's' -ScriptBlock { param($x) [pscustomobject]@{function = 'Invoke-Steppable'; x=$x; a=$a; __a=$__a }}
That code outputs
function x a __a
-------- - - ---
Invoke-Call c c c
Invoke-Steppable s s
The following, I think, is noteworthy about that output:
$ais accessible both ways-ScriptBlockis invoked. That is because both the functions and-ScriptBlockare bound to the sameSessionState. Both functions have parameter$ain the function's scope. That scope becomes an ancestor scope to-ScriptBlockwhen it is invoked so$ais visible from-ScriptBlock.$__ais accessible when-ScriptBlockis invoked byInvoke-Call. This is a similar situation to (1). When the scriptblock from[scriptblock]::Create()is invoked it is bound to theSessionStateofInvoke-Callwhich is the sameSessionStateas-ScriptBlock. So$ais visible from-ScriptBlock.$__ais not accessible when-ScriptBlockis invoked byInvoke-Steppable.
This suggests the script block from [scriptblock]::Create() that is invoked by SteppablePipeline is not bound to the same SessionState as -ScriptBlock.
To what session state does that script block get bound?
__aby the variable name..SessionStatein CompiledScriptBlock.cs. I wonder if that's an indication that the scriptblock is never bound to anySessionState.