June 3rd, 2011

Invoke-Expression considered harmful

PowerShell Team
PowerShell Team

The PowerShell team frequently gets questions that start out “how do I get the quoting right for…” and the answer turns out to usually be – there is a simpler way – don’t use Invoke-Expression.

The problem arises when trying to run some command external to PowerShell.  Some common reasons people try Invoke-Expression:

  • running some command with a space in the path
  • some command takes an argument with characters that have special meaning in PowerShell, e.g. curly braces (‘{‘ and ‘}’)
  • some command argument needs to use a PowerShell variable, perhaps as part of a quoted argument

If you’re just running some command external to PowerShell (exe, cmd, etc.) and you’re using Invoke-Expression, you are just making things more difficult than you need to.

So what’s wrong with Invoke-Expression then?

  • It complicates getting quoting right
  • It makes maintaining your script harder
  • It’s slower than the alternatives
  • And maybe worst of all – it opens up a script to code injection attacks

If Invoke-Expression isn’t the right way – then what is?

If you’re running some command and the command path has spaces in it, then you need the command invocation operator ‘&’ (see help about_operators, look for “call operator”).

If your command runs, but your arguments are wrong, then there is a good chance you are getting the quotes wrong.  Invoke-Expression doesn’t help at all in this case, it just makes the problem more complicated. 

The bottom line: Invoke-Expression is a powerful and useful command for some scenarios such as creating new scripts at runtime, but in general, if you find yourself using Invoke-Expression, you should ask yourself, or maybe a respected colleague if there is a better way.

Jason Shirk
Windows PowerShell Team

Category
PowerShell

Author

PowerShell Team
PowerShell Team

PowerShell is a task-based command-line shell and scripting language built on .NET. PowerShell helps system administrators and power-users rapidly automate tasks that manage operating systems (Linux, macOS, and Windows) and processes.

2 comments

Discussion is closed. Login to edit/delete existing comments.

  • Daniel Schroeder

    One thing I like about Invoke-Expression is that I can store the command I want it to run in a string variable, and then right before invoking it I can display the command, so in the output I can see exactly what expression is being ran. I find this very useful for troubleshooting things like calling other console executables with parameters.

    For example, this is a common pattern I use:
    ```
    [string] $command = "$someExeFilePath...

    Read more
    • Robert HoltMicrosoft employee

      The following would be an injection attack:

      function Invoke-MyCommand
      {
      param([string]$Name)

      Write-Output "Hello $Name"
      }

      $Value = "`"; Remove-Item -Force -Recurse /"

      Invoke-Expression "Invoke-MyCommand -Name `"$Value`"" # Deletes root filesystem

      & "Invoke-MyCommand" -Name $Value # Prints 'Hello "; Remove-Item -Force -Recurse /'

      In the Invoke-Expression case, some values of $Value subvert the string to bypass Invoke-MyCommand.
      When & is used, that's not possible.

      For recording things like the command being run,...

      Read more