Expanding Strings And Environment Variables in PowerShell

January 2, 2011

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%”)
%USERNAME%\%USERDOMAIN%

 

To expand it we need to use the the [System.Environment]::ExpandEnvironmentVariables static method:

PS > [System.Environment]::ExpandEnvironmentVariables(“%USERNAME%\%USERDOMAIN%”)
User1\Domain.com

 

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.

 

function Expand-String
{
  
param(
       [Parameter(Mandatory
=$true,Position=0,ValueFromPipeline=$true)]
       [
System.String]$Value,

       [switch]$EnvironmentVariable
   )

   if($EnvironmentVariable) {
      [
System.Environment]::ExpandEnvironmentVariables($Value)
   }
  
else
   {
     
$ExecutionContext.InvokeCommand.ExpandString($Value)
   }
}

## 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
User1\Domain.com

# piping values
PS > %USERNAME%\%USERDOMAIN%| Expand-String -EnvironmentVariable
User1\Domain.com

PS > ‘Process name: $($p.name) | Expand-String
Process name: powershell















Add comment
facebook linkedin twitter email

Leave a Reply to Matt Cancel Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

4 comments

  1. TaoDecember 19, 2011 ב 10:31

    Hi, the technique above is very handy, and of course most of what you say is completely correct, but the following statement is very misleading:

    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.

    In fact, ExpandString is just as unsafe: the only difference is that it means “Injected” code needs to use a variable expression like “$()”:

    $ExecutionContext.InvokeCommand.ExpandString(‘$(Write-Host “I gotz your data”)’)

    In other words, your Expand-String function is just as unsafe!

    Reply
  2. MattJuly 18, 2012 ב 21:07

    Hey, Shay-

    Thanks for the post (just now found it). Recently needed to expand a string, and did not know about the $ExecutionContext automatic variable, let alone its .InvokeCommand.ExpandString() method.

    Matt (http://vNugglets.com)

    Reply
  3. ScriptFanaticJuly 19, 2012 ב 09:10

    Thanks for the feedback Matt!

    Reply
  4. rensqltvdu@gmail.comMarch 6, 2013 ב 02:44

    Really like, camaraderie, reverence, try not to link up families over a normal hate for the purpose of an issue. code la redoute http://www.k77.fr/

    Reply