4

suppose I have the following powershell code stored in a file:

## file1.ps1

$myvar = "i am here"
if ($myvar -ne $null) {
    "($myvar) variable is Full"
} else {
    "($myvar) variable is Empty"
}

And this code is then stored in a variable:

$code_in_var = cat file1.ps1

How do I execute the code in the variable through piping?

I have tried the following:

PS C:\Mrm> $code_in_var = cat file1.ps1
PS C:\Mrm>
PS C:\Mrm> cat file1.ps1 | powershell -
PS C:\Mrm> 
PS C:\Mrm> cat file1.ps1 | Invoke-expression
Invoke-expression ; At line:1 char:23
+ if ($myvar -ne $null) {
+            ~
Missing closing '}' in statement bllock or type definition
At line:1 char:17

PS C:\Mrm>
PS C:\Mrm> $code_in_var | powershell -   ***(this does not return anything)***
PS C:\Mrm>
PS C:\Mrm>
PS C:\Mrm> $code_in_var | Invoke-expression
**same error**

However, If I run this script directly:

PS C:\Mrm> .\file1.ps1
(i am here) variable is Full

It works as it is expected to.

My question is, how do I run a full powershell code that is stored in a variable, as though it were in a file?

3
  • Why are you doing this? If it is already a .ps1, then just run it directly. Why read it into a var then try to run it. You are introducing unneeded complexity that leads to the errors your are seeing. In general, never use Invoke-Expression, as you simply are exposing yourself to unneeded risks. Commented Jun 14, 2020 at 6:01
  • thank you for the link. I'll review it. there some scenarios i deal with here at work where saving the code to a file fails due to permission issues. you are correct. running the code via a file is recommended. I needed to know how to run it from a variable as well in case the need arises. Thank you! Commented Jun 14, 2020 at 8:27
  • @KLZY To support my answer: there should be no permission issues, when creating a temporary file. Using the New-TemporaryFile cmdlet, you do not even have to care where it is stored. Let the system do the work for you. Commented Jun 14, 2020 at 8:43

4 Answers 4

6

You can store a ScriptBlock in a variable and use the & call operator like this:

$scriptBlock = {
    $myvar = "i am here"
    if ($myvar -ne $null) {
        "($myvar) variable is Full"
    } else {
        "($myvar) variable is Empty"
    }
}

& $scriptBlock

Output:

(i am here) variable is Full
Sign up to request clarification or add additional context in comments.

Comments

3

A similar thing is fully documented in the MS Docs PowerShell help file.

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-expression?view=powershell-7

You will note that at no point is the formatted multi-line code used. It's all one-liner execution code.

Note that in the call of your code, it's just this.

    @($myvar = "i am here"
    if ($myvar -ne $null) {
        "($myvar) variable is Full"
    } else {
        "($myvar) variable is Empty"
    }) | 
    Out-File -FilePath 'D:\Temp\MyCode.ps1'

    ($Command = Get-Content -Path 'D:\Temp\MyCode.ps1')

    # Results the code just runs with no Invoke-* needed
    <#
    (i am here) variable is Full
    #>

Update as per my comments

You define a var, with whatever string you want, and just type the var name. But you must do it all in the PowerShell process.

Why define PowerShell code outside the PowerShell process, just to send it to the PowerShell process?

# In a PowerShell Script development session

$MyCode = @($myvar = "i am here"
if ($myvar -ne $null) {
    "($myvar) variable is Full"
} else {
    "($myvar) variable is Empty"
})

$MyCode

# Results
<#
(i am here) variable is Full
#>

$myvar = "i am here"
if ($myvar -ne $null) {
    "($myvar) variable is Full"
} else {
    "($myvar) variable is Empty"
}

$myvar
# Results
<#
i am here
#>

# In a PowerShell terminal interactive session. 

$myvar = "i am here";if ($myvar -ne $null) {"($myvar) variable is Full"} else {"($myvar) variable is Empty"}

$myvar
# Results
<#
i am here
#>

$myvar = $null;if ($myvar -ne $null) {"$myvar variable is Full"} else {Write-Warning -Message "$myvar variable is Empty"}

# Results
<#
WARNING:  variable is Empty
#>

You cannot define a var outside of PowerShell then start PowerShell and try to use that var content. It's not in scope. All code, vars, functions, etc., have a scope and the scope must be defined in the PowerShell process

If you are saying you are wanting to run PowerShell code started from another terminal, say cmd.exe, then PowerShell has start parameters, and proper quoting, when needed, is a thing.

# There are several PowerShell startup parameters
<#
The syntax of Powershell.exe Command is:

PowerShell[.exe] 
[-EncodedCommand ]
[-ExecutionPolicy ]
[-InputFormat {Text | XML}]
[-Mta]
[-NoExit]
[-NoLogo]
[-NonInteractive]
[-NoProfile]
[-OutputFormat {Text | XML}]
[-PSConsoleFile ]
[ -Version <Windows PowerShell version> ]
[-Sta]
[-WindowStyle ]<style>
[-File <FilePath> [<Args>]]
[-Command { - | <script-block>  [-args <arg-array> ] | <string>  [<CommandParameters>] } ]
#>
powershell -Command  "Whatever command you want to run"

# Example, from a cmd.exe prompt
powershell -NoProfile -Command Get-Date
# Results
<#
Sunday, 14 June, 2020 04:31:38
#>

powershell -NoProfile -Command '{"Hello World"}'
# Results
<#
Hello World
#>

You cannot do this ...

${yourcode} | powershell

... outside of a PowerShell session. The PowerShell pipeline is only available in a PowerShell session. If you are already in a session, then again, just type and run the code.

Whatever terminal you are in has to be able to send this to PowerShell to run via the normal PowerShell startup. Yet, again, this is just introducing unneeded complexity, vs just running the script of running the code in a PowerShell interactive session directly.

2 Comments

i would really like to avoid writing to a file. any way to run the powershell code directly from the variable? with bash you can do something like printf '%s\n' "${yourcode}" | bash. Im looking for the equivalent in powershell.
Run it from where? Just modify what I show in the above. It does not have to go to a file. Yet, if like your bash example, that you are doing in an interactive way, the code must be all on one line. That does not make it a one-liner though. Bash will not run PowerShell code, you have to call PowerShell to run Powershell code.
0

You could store the code from the variable in a temporary script file and then execute it:

$code_in_var = cat .\file1.ps1

$tmpScriptFile = New-TemporaryFile | Rename-Item -NewName {$_.Name -ireplace 'tmp$', 'ps1'} -PassThru
Set-Content -Path $tmpScriptFile -Value $code_in_var
& $tmpScriptFile
Remove-Item -Path $tmpScriptFile

But if the code already originates from a file, just directly execute that instead of course.

2 Comments

i would like to avoid writing to a file. Is it possible to run the code directly from the variable it is stored in? something like $mycode | powershell -
@KLZY As far as I know, there is no such way.
0

This has been killing me, and that is how I ended up looking at this question. I know it is old. And I have a use case much like yours in my work. I don't want to leave my scripts on random client systems. I need to do more testing, but I just found that this works for a store Script in a Variable. Sorry, I don't know how to do the code formatting here. Hope this helps.

$myScript = (get-content .\\Helloworld.ps1)

$myScript | out-string | invoke-expression

In my case, I want to get $myScript, which will be a catted file from a remote server through SSH.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.