Summary: Microsoft Scripting Guy, Ed Wilson, talks about performing variable substitution inside a Windows PowerShell script block.
Hey, Scripting Guy! I am trying to create a command. The command contains variables that I would like to assign prior to creating the command. However, when I get to the script block portion of my code, it does not do the variable substitution for the value the way an expanding string normally works. Can you help me?
—SW
Hello SW,
Microsoft Scripting Guy, Ed Wilson, is here. Last week at the first ever Northern Virginia PowerShell User Group, the Scripting Wife and I found a great little tea shop. I can’t help but thinking about the scone I got there—it was pretty good.
Expanding variable values
One of the really cool things about Windows PowerShell is the expanding strings—I absolutely love them. It surely beats having to do lots of string concatenation like I had to do back in the VBScript days. To illustrate this technique, I assign a string to the value of a variable—in this case, the $a variable. I look at the value contained in the variable. This code is shown here.
PS C:\> $a = "This is a string"
PS C:\> $a
This is a string
Now, by using the expanding string, I can see the value that is contained inside the $a variable. To suppress the variable expansion, I escape it with the grave accent character as shown here.
PS C:\> "The value of `$a is $a"
The value of $a is This is a string
The problem with a script block
If, on the other hand, I want to expand the value of a variable inside a script block, it does not work. This is shown in the code that follows.
PS C:\> $a = "This is a string"
PS C:\> $a
This is a string
PS C:\> $b = {"The value of `$a is $a"}
PS C:\> $b
"The value of `$a is $a"
Solving the problem with variable expansion in a script block
The solution to expanding a variable inside a script block is to do two things. First create the script block as an expanding string. This is shown here:
PS C:\> $a = "This is a string"
PS C:\> $a
This is a string
PS C:\> $b = "The value of `$a is $a"
PS C:\> $b
The value of $a is This is a string
Now, I use the static Createmethod from the [scriptblock] class. This will create a script block. To do this, I use the [scriptblock] class and then call the Createmethod while passing the string contained in the $b variable. This is shown here.
PS C:\> [scriptblock]::Create($b)
The value of $a is This is a string
I can confirm that it is in fact a script block by piping the results to the Get-Member cmdlet as shown here:
PS C:\> [scriptblock]::Create($b) | gm
TypeName: System.Management.Automation.ScriptBlock
Name MemberType Definition
---- ---------- ----------
CheckRestrictedLanguage Method void CheckRestrictedLanguage(System.Collection...
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetNewClosure Method scriptblock GetNewClosure()
GetObjectData Method void GetObjectData(System.Runtime.Serializatio...
GetPowerShell Method powershell GetPowerShell(Params System.Object[...
GetSteppablePipeline Method System.Management.Automation.SteppablePipeline...
GetType Method type GetType()
Invoke Method System.Collections.ObjectModel.Collection[psob...
InvokeReturnAsIs Method System.Object InvokeReturnAsIs(Params System.O...
ToString Method string ToString()
Ast Property System.Management.Automation.Language.Ast Ast ...
Attributes Property System.Collections.Generic.List[System.Attribu...
File Property string File {get;}
IsFilter Property bool IsFilter {get;set;}
Module Property psmoduleinfo Module {get;}
StartPosition Property System.Management.Automation.PSToken StartPosi...
Now, the cool thing about this is that I can also store the script block into another variable. This is shown here:
$sb = [scriptblock]::Create($b)
After I have stored the script block into the variable, I can also call any of the methods or properties of the script block. For example, here is the AST:
PS C:\> $sb.Ast
ParamBlock :
BeginBlock :
ProcessBlock :
EndBlock : The value of $a is This is a string
DynamicParamBlock :
ScriptRequirements :
Extent : The value of $a is This is a string
Parent :
It is not horribly exciting in this example, but for more complex code, it is definitely exciting stuff. We have a great Hey, Scripting Guy! Blog post written by Bartek Bielawski, which offers several good ideas for further exploration: Learn How IT Pros Can Use the PowerShell AST.
SW, that is all there is to using variable expansion and substitution in a Windows PowerShell script block. Join me tomorrow when I will talk about way cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy