dan-gph
dan-gph

Reputation: 16909

Calling functions from closures in Powershell

I have a function that returns a script block that calls another function. (That may sound overly complicated, but it makes sense in the real code.)

It works in the ISE but not in the regular console.

Am I doing some wrong, or is this a bug in PowerShell? Is there a workaround?

The following is some minimal code that shows the problem:

function SomeFunc([string]$name)
{
    "Hello, $name!"
}

function GetBlock([string]$name)
{
    { SomeFunc $name }.GetNewClosure()
}

$block = GetBlock("World")

& $block

Please put the code in a file and execute that to see the error. If you just paste it into the console, then there won't be an error.

When I run it in the ISE by pressing F5, I get the expected result:

Hello, World!

However, when I run it in the regular console, I get an error:

SomeFunc : The term 'SomeFunc' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At E:\scratch\Untitled4.ps1:8 char:7
+     { SomeFunc $name}.GetNewClosure()
+       ~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (SomeFunc:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

This is my $psversiontable:

Name                           Value
----                           -----
PSVersion                      5.1.16299.251
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.16299.251
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Upvotes: 3

Views: 262

Answers (1)

WileCau
WileCau

Reputation: 2197

Setting the scope of the function being called in the script block to global gives the desired Hello, World!.

function global:SomeFunc([string]$name)
{
    "Hello, $name!"
}

Note that making SomeFunc global causes it to remain available after the script finishes executing, so you need to be careful with naming to avoid masking some other command.

Upvotes: 3

Related Questions