ScriptBlock created in a module works incorrectly if execute it separately. - by Oleg Shevnin

Status : 


Sign in
to vote
ID 559223 Comments
Status Active Workarounds
Type Bug Repros 6
Opened 5/14/2010 11:19:52 AM
Access Restriction Public


The scriptblock variable that was created in a module may work incorrectly if Invoke it outside the original runspace. 
It looks like the following variables become null is this scenario: $_, $args, $input, $this, $pscmdlet
Sign in to post a comment.
Posted by Oleg Shevnin on 8/20/2010 at 5:58 AM
Thank you for the workaround. Unfortunately it doesn't work perfect.

Imagine that these two parts of the script are completely independent (one developer creates a module another one - the script that uses data returned by the module). In this case module developers know nothing about the environment there modules will be executed in. So the solution (or even "best practice") means adding "GetNewClosure()" workaround to ANY scriptblock in ANY module - just in case - to workaround possible issues.

Doesn't sound good :(
Posted by Jason M Archer on 7/21/2010 at 9:44 AM
I don't think this is a bug. Script blocks run in the context they were created in (although $_ being broken may be a bug). The easy solution is to turn the script block into a closure with {}.GetNewClosure().
Posted by Kirk Munro on 5/14/2010 at 11:33 AM
This is by far the worst PowerShell bug to date, with huge impact on tools built on top of PowerShell forcing them to cut functionality or impose unrealistic restrictions on end users (such as not using pipelines in PowerShell modules). :(

Here's another reproduction scenario that doesn't involve C#:

$module = "${env:temp}\a.psm1"
$myvar = 42| Add-Member -Name MyProp -MemberType ScriptProperty -Value { Get-process | %{$_} } -PassThru
Export-ModuleMember -Variable myvar
'@ > $module

$ps = [powershell]::Create()
$null = $ps.AddCommand('Import-Module').AddArgument($module)
$null = $ps.Invoke()
$null = $ps.Commands.Clear()
$null = $ps.AddScript('$myvar')
$ps.Invoke() | % { $_.MyProp }