In PowerShell, when you enclose a string that contains variables (preceded by a dollar sign) in double quotation marks, the variables are replaced with the variable’s value. For example:
PS > $i = 5
PS > “The value of $i is $i.”
The value of 5 is 5.
When the string is enclosed a string in single-quotation marks, the string is passed as is, no substitution is performed.
PS > ‘The value of $i is $i.’
The value of $i is $i
What if we want to expand single quoted strings? PowerShell maintains a predefined set of variables called Automatic Variables. Each time you launch PowerShell these variables are created. One of the variables is $ExecutionContext. $ExecutionContext is added by the PowerShell engine and it provides access to the command, provider, host, event manager, and session-state information for the current instance of the Windows PowerShell runtime.
One of the $ExecutionContext members is InvokeCommand. It provides access to the command methods that can be used to expand strings, invoke scripts, and create new script blocks. $ExecutionContext.InvokeCommand has a method called ExpandString(). This method expands a specified string but in addition to double quoted strings, it can also be used to expand strings enclosed in single quotes.
PS > $a,$b,$c = 1,2,3
PS > $string = ‘a=$a b=$b c=$c’
PS > $ExecutionContext.InvokeCommand.ExpandString($string)
a=1 b=2 c=3
With regard to Environment variables, they can be accessed through the Env: drive or be referenced as $env:VARIABLENAME. PowerShell expands the latter when it’s embedded in a double quoted string.
PS > “The windows directory path is: $env:WINDIR”
The windows directory path is: C:\Windows
But if you have a string that contains an environment variable in the form of an MS-DOS variable (quoted with the percent sign character ‘%’) then ExpandString returns the value as is, no substitution occur.
PS > $ExecutionContext.InvokeCommand.ExpandString(“%USERNAME%\%USERDOMAIN%”)
To expand it we need to use the the [System.Environment]::ExpandEnvironmentVariables static method:
PS > [System.Environment]::ExpandEnvironmentVariables(“%USERNAME%\%USERDOMAIN%”)
Warning: String expansion can be also performed using the Invoke-Expression cmdlet BUT before you decide to use it you need to make sure that the code you invoke does not contain malicious expressions.
So, instead of running the above commands manually I put together the Expand-String function. With Expand-String you can expand both types of string/variables. The function defines two parameters, Value and EnvironmentVariable. Value is the string to expand and if the value is a DOS environment variable then you need to specify the EnvironmentVariable switch parameter. You can specify the values on the command line or pipe them to the function.
## Usage ##
# expand single quote strings
PS > $ps = Get-Process -Id $PID
PS > Expand-String -Value ‘Process name: $($ps.name)‘
Process name: powershell
# expand DOS Environment Variables
PS > Expand-String -Value “%USERNAME%\%USERDOMAIN%“ -EnvironmentVariable
# piping values
PS > ‘%USERNAME%\%USERDOMAIN%‘| Expand-String -EnvironmentVariable
PS > ‘Process name: $($p.name)‘ | Expand-String
Process name: powershell