1

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.

5
  • Well the file running the code won't work with Get-Content since it goes line by line without separators when put like that. The script also won't receive output into a pipeline since you only wrote the output to the host instead of returning it. Use return "($myvar) variable is Full" and the other one. you can use Get-Content if you use a foreach loop and add each line to a variable separated by a newline to a variable that you then converted to a script block Commented Jun 22, 2020 at 21:34
  • thanks for the comment. but i have no idea how to do the for loop part you mentioned. seems like a roundabout way though. @Bill_Stewart suggestion looks promising but fails for me. Commented Jun 22, 2020 at 21:44
  • @Bill_Stewart i tried [scriptblock]::Create("$scriptBlock") | iex and i still get errors. I tried it without the quotes a well and it still failed. Commented Jun 22, 2020 at 21:46
  • 2
    As @mklement0's answer demonstrates, Get-Content's -raw switch will read the whole file instead of line by line like I stated in my comment. Commented Jun 22, 2020 at 22:05
  • Thanks, @NekoMusume, but note that return is never necessary: any statement whose output is neither captured nor redirected is implicitly output (returned) to the success output stream, which by default prints to the host (console). Commented Jun 22, 2020 at 23:10

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0
$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

Comments

0

You can use out-string to convert output into string.

cat C:\Users\J\testcode.ps1 | out-string | Invoke-Expression

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.