5

I found this awesome post: Using Invoke-Command -ScriptBlock on a function with arguments

I'm trying to make the function call (${function:Foo}) dynamic, as in I want to pass the function name.

I tried this:

$name = "Foo"
Invoke-Command -ScriptBlock ${function:$name}

but that fails. I also tried various escape sequences, but just can't get the function name to be dynamic.


EDIT: For clarity I am adding a small test script. Of course the desired result is to call the ExternalFunction.

Function ExternalFunction()
{
  write-host "I was called externally"
}

Function InternalFunction()
{
    Param ([parameter(Mandatory=$true)][string]$FunctionName)
    #working: Invoke-Command -ScriptBlock ${function:ExternalFunction}
    #not working: Invoke-Command -ScriptBlock ${invoke-expression $FunctionName}
    if (Test-Path Function:\$FunctionName) {
    #working,but how to use it in ScriptBlock?
    }
}

InternalFunction -FunctionName "ExternalFunction"
Community
  • 1
  • 1
Dennis G
  • 21,405
  • 19
  • 96
  • 133

3 Answers3

6

Alternate solution:

function foo {'I am foo!'}

$name = 'foo'

$sb = (get-command $name -CommandType Function).ScriptBlock
invoke-command -scriptblock $sb

I am foo!

mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • I didn't mean that you should add a working example. I was happy that the example you provided worked! :-) Thanks – Dennis G Feb 09 '13 at 20:00
  • 2
    Just for future reference, this will actually fail if you use it with an advanced function that has a Begin, Process or End block. You'll get an exception about containing more than one clause. You can get around it by using the call operator instead of Invoke-Command though. So something like this: & $sb "Some Function Argument" – user2233949 Jun 28 '17 at 15:25
2

as simple as :

invoke-expression  $name

or if you want to keep invoke-commande for remoting for example

Invoke-Command -ScriptBlock { invoke-expression  $name}
Loïc MICHEL
  • 24,935
  • 9
  • 74
  • 103
  • `invoke-expression` works outside a function. But when using it together with invoke command within a function I get a `"Cannot validate argument on parameter 'ScriptBlock'. The argument is null. Supply a non-null argument and try the"` – Dennis G Feb 09 '13 at 19:37
  • you have an unwanted $ before your scriptblock – Loïc MICHEL Feb 09 '13 at 19:54
2

You could try the following. It tests if the name specified is a valid function before it attempts to run it:

$myfuncnamevar = "Foo"
Invoke-Command -ScriptBlock {
    param($name)
    if (Test-Path Function:\$name) { 
        #Function exists = run it
        & $name
    }
} -ArgumentList $myfuncnamevar
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • Test-Path does work, but how would I call it within the Invoke-Command? – Dennis G Feb 09 '13 at 19:36
  • 1
    I put a line at the bottom to explain it. Updated with solution now. Remember that the function needs to exist on the remote computer. If this is a local funciton, you need to pass it in the scriptblock. – Frode F. Feb 09 '13 at 19:38