192

I need to display all configured environment variables in a PowerShell script at runtime. Normally when displaying environment variables I can just use one of the following at the shell (among other techniques, but these are simple):

gci env:*
ls Env:

However, I have a script being called from another program, and when I use one of the above calls in the script, instead of being presented with environment variables and their values, I instead get a list of System.Collections.DictionaryEntry types instead of the variables and their values. Inside of a PowerShell script, how can I display all environment variables?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
codewario
  • 19,553
  • 20
  • 90
  • 159

10 Answers10

265

Shorter version:

gci env:* | sort-object name

This will display both the name and value.

Jim Aho
  • 9,932
  • 15
  • 56
  • 87
jaymjarri
  • 3,048
  • 1
  • 18
  • 7
  • 1
    Could you explain why it behaves like that and how your command fixes it, please? – David Ferenczy Rogožan Sep 06 '18 at 12:43
  • 19
    That's the sign of progress because `env` was too easy. Damn you M$ people. – matcheek Apr 03 '19 at 07:19
  • 2
    I want to add that this behavior was something I encountered in PowerShell 4, but as of 5.1+ I can use the variants shown in the question within a script and expect it to display the variable name and value. Note that `gci env:` will now sort the variables by `Name`. though `gci env:*` does *not*. – codewario Sep 10 '21 at 17:35
  • 2
    I'm assuming that by _shorter_ you mean relative to the [OP's own answer](https://stackoverflow.com/a/39800606/45375). However, the omission of `Out-String` is crucial with respect to the question as asked. If you simply want to list all environment variables including their values in PowerShell with nice formatting, `gci env:` will do (no need for `*`, no need for `Sort-Object`, as without the `*` the output is automatically sorted by name). – mklement0 Oct 09 '22 at 00:26
82

Shortest version (with variables sorted by name):

gci env:
Vlad Rudenko
  • 2,363
  • 1
  • 24
  • 24
19

I finally fumbled my way into a solution by iterating over each entry in the dictionary:

(gci env:*).GetEnumerator() | Sort-Object Name | Out-String
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
codewario
  • 19,553
  • 20
  • 90
  • 159
  • doesn't run on Linux for me. Are you missing `gci` to get the child items? – Thufir Jan 22 '20 at 22:16
  • I haven't tried this on powershell core, but gci is in my answer. Note that this question is for [powershell] and not [powershell-core], so solutions may not work for the latter. – codewario Jan 23 '20 at 01:30
  • You can simplify to `gci env: | Out-String` (in _both_ PowerShell editions). Please reconsider which answer you've accepted, given that you clearly needed an _explicit stringification_ of the `[System.Collections.DictionaryEntry]` instances (though it is unclear why), which the [currently accepted answer](https://stackoverflow.com/a/45570821/45375) lacks. As it stands, the currently accepted answer doesn't addresses your problem, and is also a poor answer to the _general_ question of how to list environment variables in PowerShell, given that `gci env:` is enough. – mklement0 Oct 11 '22 at 22:33
15

I don't think any of the answers provided are related to the question. The OP is getting the list of Object Types (which are the same for each member) and not the actual variable names and values. This is what you are after:

gci env:* | select Name,Value

Short for:

Get-ChildItem Env:* | Select-Object -Property Name,Value
Mauricio_BR
  • 151
  • 1
  • 2
14

Short version with a wild card filter:

gci env: | where name -like 'Pro*'
Emil
  • 2,196
  • 2
  • 25
  • 24
  • 2
    You can also skip the pipeline and simply use a wildcard filter with `Get-ChildItem`. For example: `gci env:Pro*` – codewario Feb 03 '22 at 18:35
10

This command works also:

dir env:
Christopher Scott
  • 2,676
  • 2
  • 26
  • 26
4

There are several ways to get all environment variables in Powershell

 [System.Environment]::GetEnvironmentVariables()
 or
 dir env:

To get environment variable by name

[System.Environment]::GetEnvironmentVariable("USERNAME")
 $env:USERNAME
3

tl;dr

Since you were looking for a friendly string representation of the environment-variable name-value pairs:

gci env: | oss

oss is a built-in wrapper function for Out-String -Stream, and therefore returns each name-value pair as its own string; pipe to Out-String (without -Stream) to get a single, multi-line string (albeit one that invariably and unexpectedly has a trailing newline - see GitHub issue #14444).


To list the names and values of all environment variables in PowerShell, sorted by name,[1] list the content (child items) of the env: PowerShell drive using the Get-ChildItem cmdlet (a built-in alias of which is gci):

# 'gci' is a built-in alias of the 'Get-ChildItem' cmdlet.
# Avoid alias 'ls', because on Unix-like platforms 
# it isn't defined and instead refers to the standard utility of that name.
# The output is implicitly *sorted by variable name*.
gci env:

# Use *wildcards* to list variables by *name pattern*; e.g, all whose
# name starts with "home"
gci env:home*

The above outputs objects, namely instances of [System.Collections.DictionaryEntry] describing each variable as a name-value pair, with .Key (.Name) and .Value properties. PowerShell's for-display formatting system automatically renders these in a friendly two-column format.

  • To list environment-variable names only:

    gci env: -Name
    
    # Alternative, using property access:
    (gci env:).Name
    
  • To get a specific environment-variable's value, e.g. USERNAME, it's easiest to use namespace variable notation:

    # Output the value of environment variable "USERNAME"
    $env:USERNAME
    
    # Alternative, using gc (alias of Get-Content)
    # Needed if the name is stored in a variable.
    gc env:USERNAME
    

If you stringify these objects with (potentially implied) .ToString():

  • In Windows PowerShell, they uselessly stringify as their type name, i.e. as verbatim 'System.Collections.DictionaryEntry'

  • In PowerShell (Core) 7, they now more meaningfully stringify as '[<name>, <value>]'

  • Try with (% is a built-in alias of the ForEach-Object cmdlet):

    gci env: | % tostring
    
    # Ditto with Write-Host, which also uses .ToString() stringification
    gci env: | Write-Host
    

If you want to stringify them as they would print to the display, using the friendly two-column format, use the Out-String cmdlet:

# Outputs *friendly* string representations
gci env: | oss # 'oss' is a built-in wrapper function for 'Out-String -Stream'

Note: If you use Out-String without -Stream, you get a single, multi-line string as the output, though note that it will have a trailing newline.[2]


[1] Note that using Get-ChildItem / gci with env:*, i.e. wildcard character * following the drive specification env: - is not only unnecessary for getting all variables, it actually results in unsorted output.

[2] That a trailing newline is invariably appended is problematic, as discussed in GitHub issue #14444

mklement0
  • 382,024
  • 64
  • 607
  • 775
3

Long environment variable values get truncated by default.

This is one quick way to get a sorted list of environment variables, with full values:

Get-ChildItem env:* | Sort-Object Name | Format-List
GaTechThomas
  • 5,421
  • 5
  • 43
  • 69
0

If you're using PowerShell Core(6 or above) (pwsh: https://github.com/PowerShell/PowerShell), you can also use ls env:

WeihanLi
  • 87
  • 7
  • What is `list`? I see no such command in PowerShell (Core) v7.2.4. Did you mean `ls`? If so, that's [yet another alias for `Get-ChildItem`](https://stackoverflow.com/questions/39800481/display-all-environment-variables-from-a-running-powershell-script#comment122736361_69407908) and also already stated in the question. – Lance U. Matthews May 22 '22 at 03:22
  • 1
    Yeah, it should be `ls`, sorry for the miss-leading, thanks for your correction @LanceU.Matthews – WeihanLi May 22 '22 at 13:42