2

I've got this ps snippet:

function myFuncWithArgs($arg) { 
    Write-Output $arg 
}

$temp = 'sometext'

$cFunc = 'myFuncWithArgs' 
& $cFunc $temp

it works but I need the $temp to be on the same line as $cFunc and work the same. This does not work:

$cFunc = 'myFuncWithArgs' $temp
& $cFunc

is this possible in pshell?

mklement0
  • 382,024
  • 64
  • 607
  • 775
bitbar
  • 121
  • 1
  • 10

3 Answers3

4

It looks like you're trying to store a complete command (executable + arguments) in a variable for later execution on demand.

Use a script block ({ ... }) for that, which you can call on demand with &, the call operator:

# Define the full command as a script block.
$scriptBlock = { myFuncWithArgs $temp }

# Invoke it.
# You may also pass arguments to it, but that only makes sense
# if it is designed to accept them, e.g. via $args
& $scriptBlock

Note:

  • & does not work with a string containing a complete command. Its argument must either be a script block, as shown, or command name or executable path, and any arguments to pass to that script block / command / executable must be specified separately, e.g.
    & { Write-Output $args } arg1 ... or & $pathToExecutable arg1 ...
  • Read on for how execute a complete command stored in a string, which can be a security risk, however.

The above uses a script-block literal.
To create a script block from a string, use [scriptblock]::Create():

# IMPORTANT: 
#  Be sure that you either fully control or implicitly trust
#  the content of this string, so as to prevent execution of unwanted code.
$commandString = 'myFuncWithArgs $temp'

$scriptBlock = [scriptblock]::Create($commandString)

& $scriptBlock

You mention Read-Host, i.e. prompting the user, as the source of your command string, in which case the caveat under "IMPORTANT:" above definitely applies.

  • If the risk of execution arbitrary user-supplied commands is acceptable to you, you could simply use Invoke-Expression $commandString - but note that Invoke-Expression is generally discouraged precisely for its ability to execute arbitrary code stored in a string.

  • However, there is middle ground, which does require [scriptblock]::Create():

    • Before invoking the script block, you can call its .CheckRestrictedLanguage() method to ensure that the resulting command only contains commands permitted in Restricted language mode, with configurability as to which specific commands and variables are permitted.
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • this works: `$scriptBlock = {myFuncWithArgs 'some text'} & $scriptBlock` but if I try to use Read-Host -prompt and paste into the console `{myFuncWithArgs 'some text'}` then I get an error: `& : The term '{myFuncWithArgs 'some text'}' is not recognized as the name of a cmdlet, function, script file, or operable program.` – bitbar Apr 19 '23 at 15:32
  • I'm using Read-Host to listen to data from a parent NodeJS script,. The NodeJS script works fine with single functions: `spawnedChild.stdin.write("functionNOArgs\r");` , but I still can't get it to work with args: `spawnedChild.stdin.write("functionWithArgs\r 'R:/file.txt'");` . I should've started the thread including this info but I reckoned that I was just messing up the syntax or some other minor issue. – bitbar Apr 19 '23 at 16:25
  • 1
    finally, it's working! When writing a function and arg, there is no need for \r after the function, so: `spawnedChild.stdin.write("functionWithArgs 'R:/file.txt'");` with `[scriptblock]::Create` = solution, thanks! – bitbar Apr 19 '23 at 16:31
  • Glad to hear it, @bitbar. Indeed, `\r` shouldn't be used, because PowerShell expects a given commands to either be on a single line or use explicit line continuation with `\`` (the exception is when a command is _syntactically incomplete_, in which case PowerShell looks at the next line too, such as when placing a `|` at the end of a line). – mklement0 Apr 19 '23 at 16:38
2

You can assign to multiple variables at once, thus keeping things on the same line:

$cFunc,$cArgs = 'myFuncWithArgs',$temp
& $cFunc @cArgs
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
0

Invoke the function without brackets, and the parameters without commas and with white spaces.

function Dartagnan($a, $b)
{
$c = $a + $b;
Write-Host $c;
#result is 12;
}
Dartagnan 5 7;
Read-Host;
D'Artagnan
  • 11
  • 3