Reputation: 4289
Given I have:
$a = "world"
$b = { write-host "hello $a" }
How do I get the resolved text of the script block, which should be the entre string including write-host:
write-host "hello world"
UPDATE: additional clarifications
If you just print $b
you get the variable and not the resolved value
write-host "hello $a"
If you execute the script block with & $b
you get the printed value, not the contents of the script block:
hello world
This question is seeking a string containing the contents of the script block with the evaluated variables, which is:
write-host "hello world"
Upvotes: 8
Views: 11340
Reputation: 360
Another way to do it is:
$a = "world"
$b = "write-host ""hello $a"""
$b
The output is:
write-host "hello world"
Upvotes: 0
Reputation: 25021
As in the original question, if your entire scriptblock contents is not a string (but you want it to be) and you need variable substitution within the scriptblock, you can use the following:
$ExecutionContext.InvokeCommand.ExpandString($b)
Calling .InvokeCommand.ExpandString($b)
on the current execution context will use the variables in the current scope for substitution.
The following is one way to create a scripblock and retrieve its contents:
$a = "world"
$b = [ScriptBlock]::create("write-host hello $a")
$b
write-host hello world
You can use your scriptblock notation {}
as well to accomplish the same thing, but you need to use the &
call operator:
$a = "world"
$b = {"write-host hello $a"}
& $b
write-host hello world
A feature to using the method above is that if you change the value of $a
at any time and then call the scriptblock again, the output will be updated like so:
$a = "world"
$b = {"write-host hello $a"}
& $b
write-host hello world
$a = "hi"
& $b
write-host hello hi
The GetNewClosure()
method can be used to create a clone of the scriptblock above to take a theoretical snapshot of the scriptblock's current evaluation. It will be immune to the changing of the $a
value later the code:
$b = {"write-host hello $a"}.GetNewClosure()
& $b
write-host hello world
$a = "new world"
& $b
write-host hello world
The {}
notation denotes a scriptblock object as you probably already know. That can be passed into Invoke-Command
, which opens up other options. You can also create parameters inside of the scriptblock that can be passed in later. See about_Script_Blocks for more information.
Upvotes: 15