PowerShell Cookbook

Search

Categories

 

On this page

Archive

Blogroll

Disclaimer
I work for Microsoft.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 218
This Year: 18
This Month: 0
This Week: 0
Comments: 529

Sign In

 Wednesday, May 10, 2006
Wednesday, May 10, 2006 7:22:20 AM (Pacific Daylight Time, UTC-07:00) ( )

In a recent comment, David asked how to access environment variables in PowerShell.  This is something that we normally just document explicitly: $env:Variable

However, that explicit documentation is actually a shortcut for a feature you may not know about.  It’s a little like dividing fractions – you can do it without ever knowing why it works, just that it works.  Of course, it’s nice to be able to explain why.

As you may know, the ‘$’ character is the way that we access variables in PowerShell.  The probing student might then ask, “Why can we access environment variables the same way we access normal variables.  Isn’t ‘Env:’ the environment provider?  And specific environment variables are children of it?”

Those are good questions.  This is because the Environment provider shares something in common with several other providers – namely support for the *-Content set of core Cmdlets:

[C:\temp]
PS:11 > "hello world" > test

[C:\temp]
PS:12 > get-content test
hello world

[C:\temp]
PS:13 > get-content variable:ErrorActionPreference
Continue

[C:\temp]
PS:14 > get-content function:more
param([string[]]$paths);  if(($paths -ne $null) -and ($paths.length -ne 0))  { ...
       Get-Content $local:file | Out-Host -p    }  }  else { $input | Out-Host ...

[C:\temp]
PS:15 > get-content env:systemroot
C:\WINDOWS

For providers that support the content cmdets, we let you interact with this content through a special variable syntax:

[C:\temp]
PS:16 > $function:more
param([string[]]$paths);  if(($paths -ne $null) -and ($paths.length -ne 0))  { …
       Get-Content $local:file | Out-Host -p    }  }  else { $input | Out-Host …

[C:\temp]
PS:17 > $variable:ErrorActionPreference
Continue

[C:\temp]
PS:18 > $c:test
hello world

[C:\temp]
PS:19 > $env:systemroot
C:\WINDOWS

This variable syntax for content management allows you to both get, and set content:

[C:\temp]
PS:20> $function:more = { $input | less.exe }

[C:\temp]
PS:21> $function:more
$input | less.exe

Now, when it comes to accessing complex provider paths using this method, you’ll quickly run into naming issues:

[C:\temp]
PS:22> $c:\temp\test.txt
Unexpected token '\temp\test.txt' in expression or statement.
At line:1 char:17
+ $c:\temp\test.txt <<<<

The solution to that lies in our escaping support for complex variable names:

[C:\temp]
PS:31 > ${1234123!@#$!@#$12$!@#$@!} = "Crazy Variable!"

[C:\temp]
PS:32 > ${1234123!@#$!@#$12$!@#$@!}
Crazy Variable!

[C:\temp]
PS:33 > dir variable:\1*

Name                           Value
----                           -----
1234123!@#$!@#$12$!@#$@!       Crazy Variable!

… and the content equivalent:

[C:\temp]
PS:34 > ${c:\temp\test.txt}
hello world

So, the way to access environment variables isn’t so unique after all. 

Comments [3] | | # 
Thursday, July 13, 2006 4:27:29 AM (Pacific Daylight Time, UTC-07:00)
PSMDTAG:FAQ: Environment Variables - how I access them? ANSWER: $ENV:VAR

PSMDTAG:FAQ: How do use ANY character in a variable name? ANSWER: ${ any chars}=value

PSMDTAG:INTERNAL: Environmental variables exposed as a namespace drive.

Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
Jeffrey Snover
Friday, August 18, 2006 5:34:13 AM (Pacific Daylight Time, UTC-07:00)
I met a problem when I want to run a sequence of batch files in PowerShell. The envioronment variables did not pass between batch files as well as did not pass to PS $env:

PS D:\myworkspace> gc a.bat
set mypath=c:\WINDOWS
PS D:\myworkspace> gc b.bat
cd %mypath%
PS D:\myworkspace> .\a.bat

D:\myworkspace>set mypath=c:\WINDOWS
PS D:\myworkspace> .\b.bat

D:\myworkspace>cd
D:\myworkspace
PS D:\myworkspace> $env:mypath
PS D:\myworkspace>
bin
Friday, August 18, 2006 6:04:06 AM (Pacific Daylight Time, UTC-07:00)
Yes -- this is because PowerShell loads cmd.exe as a child process (as does cmd.exe if you call it explicitly.) See this post for info about that problem, and the solution: http://www.leeholmes.com/blog/NothingSolvesEverythingPowerShellAndOtherTechnologies.aspx

Lee
Name
E-mail
Home page

Comment (Some html is allowed: b, blockquote@cite, em, i, strike, strong, sub, super, u)  

Enter the code shown (prevents robots):