NOTE: I\'m using PowerShell 2.0 on Windows Vista.
I\'m trying to add support for specifying build arguments to psake, but I\'ve run into some strange PowerShell var
I don't think this is considered to be a bug by the PowerShell team, but I can at least shed some light on how it works.
Any script block that's defined in a script or script module (in literal form, not dynamically created with something like [scriptblock]::Create()) is bound to the session state of that module (or to the "main" session state, if not executing inside a script module.) There is also information specific to the file that the script block came from, so things like breakpoints will work when the script block is invoked.
When you pass in such a script block as a parameter across script module boundaries, it is still bound to its original scope, even if you invoke it from inside the module.
In this specific case, the simplest solution is to create an unbound script block by calling [scriptblock]::Create() (passing in the text of the script block object that was passed in as a parameter):
. ([scriptblock]::Create($properties.ToString()))
However, keep in mind that there is potential for scope problems in the other direction, now. If that script block relies on being able to resolve variables or functions that were available in the original scope, but not from the module where you've invoked it, it will fail.
Since the intention of the $properties block appears to be to set variables and nothing else, I would probably pass in an IDictionary or Hashtable object instead of a script block. That way all of the execution takes place out in the caller's scope, and you get a simple, inert object to deal with inside the module, with no scope silliness to worry about:
function Test {
param(
[ValidateNotNull()]
[Parameter(Position=0,Mandatory=0)]
[System.Collections.IDictionary]$properties = @{}
)
# Setting the default
$message = "Hello, world!"
Write-Host "After setting defaults, message is: $message"
foreach ($dictionaryEntry in $properties.GetEnumerator())
{
Set-Variable -Scope Local -Name $dictionaryEntry.Key -Value $dictionaryEntry.Value
}
Write-Host "After importing properties, message is: $message"
}
Caller file:
Import-Module .\repoCase.psm1
Write-Host "Before execution - In global scope, message is: $message"
Test -properties @{ Message = 'New Message' }
Write-Host "After execution - In global scope, message is: $message"
Remove-Module repoCase