3

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
3
  • I just copied your code into the console and got "Hello, World!" Commented Mar 23, 2018 at 2:17
  • @MikeShepard, hmmm, it seems that if you paste it into to console, then it works, but not if you run it from a file. I will update my question. Thanks. Commented Mar 23, 2018 at 2:24
  • 2
    GetNewClosure only capture variable, but not functions. It also do it in the way, that only global scope is available to closure. It will behave the same way in ISE, if you will not use "Run (F5)" ISE command, but type file name in the console, assuming session is clean and function SomeFunc is not yet defined in global scope. Commented Mar 23, 2018 at 3:58

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.