2

one of my powershell scripts is behaving strangely. When the command is executed with the call operator (&), it works as expected. Since I am not a fan of shortcuts and the operators are not easy to read, I want to use Invoke-Expression instead. Anyway, this is not really a problem for me, but I am interested to know if this is a bug in Powershell, or if I am doing something wrong. However, this leads to the error: Invoke-Expression : No parameter was found that matches the parameter name "file". In D:\Job_Monday.PS1:10 characters:34

  • Invoke-Expression -Command $cmd1 -file $fil1 -wake $nas1 -close
  •   + CategoryInfo : InvalidArgument: (:) [Invoke-Expression], ParameterBindingException
      + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
    
    

The script:

`   [String] $cmd1 = "C:\Tools\WOL2\WOL2.exe"
`   [String] $fil1 = "C:\Tools\WOL2\WOL2.profile4.xml"
`   [String] $nas1 = "SyBackup"
`   # wake-on-LAN with call operator
`   # & $cmd1 -file $fil1 -wake $nas1 -close
`   # Wake-On-LAN with Invoke expression
`   Invoke-Expression -command $cmd1 -file $fil1 -wake $nas1 -close
Many greetings from Aachen
inl1ner
4
  • 2
    What makes you believe Invoke-Expression is meant for running binaries? You might wanted to use Start-Process however, if your intent is to run the binary on your current session you just keep using the call operator Commented Mar 25, 2022 at 16:42
  • 2
    Invoke-Expression and the call operator are not the same thing. In particular, the call operator is not a shorthand or alias for Invoke-Expression (iex is, but that's a different matter). Commented Mar 25, 2022 at 16:42
  • Thank you very much for the helpful hints. Start-Process with -ArgumentList is indeed the solution. Commented Mar 25, 2022 at 17:08
  • 1
    Do note that Start-Process is not the same thing as the call operator either, and using that instead of staying in the current session is quite different from invoking the command directly (and more cumbersome besides). It may be appropriate if your intent is to call the command and not wait for it to complete; if you combine it with waiting, however, Start-Process is seldom necessary, especially not for console commands. Commented Mar 25, 2022 at 17:19

1 Answer 1

3

First, the obligatory caveat:

  • Invoke-Expression (iex) should generally be avoided and used only as a last resort, due to its inherent security risks. Superior alternatives are usually available. If there truly is no alternative, only ever use it on input you either provided yourself or fully trust - see this answer.

Invoke-Expression accepts only a single argument that is a string containing arbitrary PowerShell code, and as such it is unrelated to &, the call operator, which accepts multiple arguments, the first of which is a command name or path, with any remaining arguments being passed to that command.

As such, & is just a syntactic variation of direct execution of commands, and it is only required in two cases:

  • If a command name (executable path) is quoted or contains variable references, it must - for syntactic reasons - be invoked with &, the call operator; see this answer for details.

  • If the command you're invoking is given in the form of a script block ({ ... }).

For instance, the following statements are equivalent:

# Direct execution
C:\Tools\WOL2\WOL2.exe -command $cmd1 -file $fil1 -wake $nas1 -close

# Direct execution, of necessity via & in this case,
# because the executable path is *quoted*
& "C:\Tools\WOL2\WOL2.exe" -command $cmd1 -file $fil1 -wake $nas1 -close

# You can also use Invoke-Command, but that is *rarely useful*
# in *local* calls; also, inside the script block the rules re
# the & operator still apply.
Invoke-Command { & "C:\Tools\WOL2\WOL2.exe" -command $cmd1 -file $fil1 -wake $nas1 -close }

Direct execution is by far the most typical form of invocation, because it guarantees:

  • synchronous execution (for console applications)
  • in the current console
  • with the invoked command's output streams directly connected to the current session, so that output can be captured, relayed, or redirected / suppressed.

By contrast, Start-Process is only called for in exceptional circumstances:

  • If you want to run in a new console window (by default), asynchronously by default (unless you pass -Wait)

  • If you want to run a GUI application synchronously, with -Wait (with direct execution GUI applications launch asynchronously).

  • If you need to launch a command elevated (as admin), with -Verb RunAs

  • If you need to launch a command with a as a different user, with -Credential

Note that there's no direct way to capture output from a Start-Process-launched process - your only option is to redirect to files, with -RedirectStandardOutput and -RedirectStandardError.


Note that there's also the Invoke-Command cmdlet, which you can think of as the cmdlet equivalent to the & operator; however:

  • It is rarely useful in local invocations; its primary purpose is remote execution of commands - see this answer for details.

  • Syntactically, it requires passing a command wrapped in a script block, as shown above, and inside that script block the usual syntax rules apply, so & may be required as well.

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.