I have been doing a lot of reading on invoke-expression (also known as iex) and I'm having trouble getting it to work for me.
My understanding is, it will run any powershell code you give to it. However, when I run my tests on it, it does not run the code.
Example:
## testcode.ps1 $myvar = "i am here" if ($myvar -ne $null) { "($myvar) variable is Full" } else { "($myvar) variable is Empty" } Now, if I cat(gc) this file and I pass it to iex, it outputs a bunch of errors. Same thing happens when I save the code into a variable and then feed the variable to iex. Neither works.
Despite the fact that I've tried numerous examples, I feel there's something minor I'm doing wrong that I'm hoping someone can point out for me.
I'm new to Windows scripting, so please bear with me. These are the results of the tests I performed:
First Test:
PS C:\Users\J> gc C:\Users\J\testcode.ps1 | iex Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string. At line:1 char:31 + cat C:\Users\J\testcode.ps1 | iex + ~~~ + CategoryInfo : InvalidData: (:PSObject) [Invoke-Expression], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand iex : At line:1 char:23 + if ($myvar -ne $null) { + ~ Missing closing '}' in statement block or type definition. At line:1 char:31 + cat C:\Users\J\testcode.ps1 | iex + ~~~ + CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException + FullyQualifiedErrorId : MissingEndCurlyBrace,Microsoft.PowerShell.Commands.InvokeExpressionCommand Second Test:
PS C:\Users\J> $scriptBlock = gc C:\Users\J\testcode.ps1 PS C:\Users\J> PS C:\Users\J> iex -Command "$scriptBlock" iex : At line:1 char:23 + $myvar = "i am here" if ($myvar -ne $null) { "($myvar) variable ... + ~~ Unexpected token 'if' in expression or statement. At line:1 char:1 + iex -Command "$scriptBlock" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand PS C:\Users\J> I'm aware that I can just run the file containing the code. However, I need help figuring out how iex works and what it is I'm doing wrong.
Please kindly advise.
52 Answers
First things first:
Invoke-Expression should generally be avoided and used only as a last resort, due to its security risks. In short: avoid it, if possible, given that 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.
For the record: in the case at hand, the superior alternative is to directly invoke the script file:
# Prepend `& `, if the script file path is quoted or references a variable. C:\Users\J\testcode.ps1 Invoke-Expression (iex) accepts multiple strings via the pipeline, and evaluates each individually, as a self-contained script.
Therefore, you must provide the contents of your script as a whole, as a single string, which is what Get-Content's (gc's) -Raw switch does[1]:
Get-Content -Raw C:\Users\J\testcode.ps1 | Invoke-Expression Alternatively, pass the script-file contents as an argument:
Invoke-Expression (Get-Content -Raw C:\Users\J\testcode.ps1) Note that passing the string to evaluate as an argument truly only accepts a single string, so the command would fail without -Raw.
[1] By default, the Get-Content cmdlet reads a file line by line, passing each line through the pipeline as it is being read.
$myvar = "I'm Here" #Using Invoke-Expression - Accepts a STRING as Input $SBCode = 'if ($Null -ne $myvar) {"($myvar) variable is Full"}' + 'else {"`$myvar variable is Empty"}' Clear-Host "Before Invoke-Expression `$myvar = $myvar" $Result = Invoke-Expression $SBCode "Invoke-Expression Returns: $Result" #Using Invoke-Command - Accepts Script Block as Input $SBCode = { if ($myvar -ne $null) { "($myvar) variable is Full" } else { "`$myvar variable is Empty" } } #End $SBCode Script Block "Before Invoke-Command `$myvar = $myvar" $Result = Invoke-Command -ScriptBlock $SBCode "Invoke-Command Returns: $Result" Results:
Before Invoke-Expression $myvar = I'm Here Invoke-Expression Returns: (I'm Here) variable is Full Before Invoke-Command $myvar = I'm Here Invoke-Command Returns: (I'm Here) variable is Full # After changing $MyVar = $Null Before Invoke-Expression $myvar = Invoke-Expression Returns: $myvar variable is Empty Before Invoke-Command $myvar = Invoke-Command Returns: $myvar variable is Empty HTH