PowerShell Automatic Variables

They are there for you, but sometimes you forget they are there… Automatic Variables! In this blog post, I will show you some examples and why they are so helpful!

What are Automatic Variables?

As the name implies, they are created automatically and are available straight away in your PowerShell session for you to use. They contain information about the user, system, default variables, runtime variables, and PowerShell settings.

Examples

Below is a list of, at least for me, useful Automatic Variables

$?

Running this will show you the result of your last command, and it will report True if it succeeded and False if it failed. For example:

C:\Users\HarmVeenstra> Get-ChildItem -Path c:\temp

        Directory: C:\Temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d----          6-6-2023     23:28                  Wallpaper
-a---         17-5-2023     10:01          14116   apps.csv
-a---         24-3-2023     14:39         764092   files.csv
-a---         25-4-2023     23:38            846   services.txt
-a---         25-4-2023     23:39           3975   services2.txt
-a---          3-5-2023     10:42           6578   ServicesFix-3.5.1.Log
-a---          8-5-2023     19:16            400   userslicenses.csv

C:\Users\HarmVeenstra> $?
True

It was True because the directory could be found. If not, it will look like this:

C:\Users\HarmVeenstra> Get-ChildItem -Path c:\tempabc
Get-ChildItem: Cannot find path 'C:\tempabc' because it does not exist.

C:\Users\HarmVeenstra> $?
False

You can use this in scripts for error handling. For example:

C:\Users\HarmVeenstra> Get-ChildItem -Path c:\tempabc
Get-ChildItem: Cannot find path 'C:\tempabc' because it does not exist.

C:\Users\HarmVeenstra> if ($? -ne 'True') {
>> Write-Warning ("Error occured..")
>> }
>> else {
>> Write-Host ("Folder was found, continuing...") -ForegroundColor Green
>> }

WARNING: Error occured..

$Error

This variable contains an array of all errors in the current PowerShell session, and it’s an excellent way to retrieve them. For example, by not enclosing True, I made an error in the first line of the if-else statement above.

C:\Users\HarmVeenstra> $Error

Errors                      : {At line:1 char:11
                              + if ($? -ne True) {
                              +           ~
                              You must provide a value expression following the '-ne' operator., At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Unexpected token 'True' in expression or statement., At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Missing closing ')' after expression in 'if' statement., At line:1 char:16
                              + if ($? -ne True) {
                              +                ~
                              Unexpected token ')' in expression or statement.}
Message                     : At line:1 char:11
                              + if ($? -ne True) {
                              +           ~
                              You must provide a value expression following the '-ne' operator.

                              At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Unexpected token 'True' in expression or statement.

                              At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Missing closing ')' after expression in 'if' statement.

                              At line:1 char:16
                              + if ($? -ne True) {
                              +                ~
                              Unexpected token ')' in expression or statement.
ErrorRecord                 : At line:1 char:11
                              + if ($? -ne True) {
                              +           ~
                              You must provide a value expression following the '-ne' operator.

                              At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Unexpected token 'True' in expression or statement.

                              At line:1 char:12
                              + if ($? -ne True) {
                              +            ~~~~
                              Missing closing ')' after expression in 'if' statement.

                              At line:1 char:16
                              + if ($? -ne True) {
                              +                ~
                              Unexpected token ')' in expression or statement.
WasThrownFromThrowStatement : False
TargetSite                  : System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject] Invoke(System.Collections.IEnumerable)
Data                        : {}
InnerException              :
HelpLink                    :
Source                      : System.Management.Automation
HResult                     : -2146233087
StackTrace                  :    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
                                 at Microsoft.PowerShell.Executor.ExecuteCommandHelper(Pipeline tempPipeline, Exception& exceptionThrown, ExecutionOptions options)

Note: If you have more error messages, you can retrieve the last one by using $error[0]

$host

This gives you information about your system. I mainly use it to display the version of PowerShell, and this looks like this:

C:\> $host

Name             : ConsoleHost
Version          : 7.3.4
InstanceId       : 1f3f2dbe-9ed8-49e0-a284-577282138344
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : nl-NL
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled  : True
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

$IsLinux, $IsMacOs, $IsWindows

These three variables can be used to determine the operating system on which you are running your scripts, which is easy if you have something specific in a script that only runs on Linux. It returns True or False, for example:

C:\> $IsLinux
False

C:\> $IsMacOS
False

C:\> $IsWindows
True

You could use this in a script like this on Windows and get output like this:

C:\> #Get free diskspace
>> if ($IsLinux) {
>> df -h
>> }>> elseif ($IsWindows) {
>> Get-PSDrive
>> }

Name           Used (GB)     Free (GB) Provider      Root                                                                 CurrentLocation
----           ---------     --------- --------      ----                                                                 ---------------
Alias                                  Alias
C                 340,12        136,06 FileSystem    C:\
Cert                                   Certificate   \
D                  79,51        159,24 FileSystem    D:\
Env                                    Environment
Function                               Function
HKCU                                   Registry      HKEY_CURRENT_USER
HKLM                                   Registry      HKEY_LOCAL_MACHINE
Temp              340,12        136,06 FileSystem    C:\Users\HarmVeenstra\AppData\Loca…
Variable                               Variable
WSMan                                  WSMan

But on Linux, you will get output like this: (Running on my Raspberry Pi 4):

PS /home/harm> #Get free diskspace
PS /home/harm> if ($IsLinux) {
>> df -h
>> }elseif ($IsWindows) {
>> Get-PSDrive
>> }
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       230G   19G  201G   9% /
devtmpfs        1.7G     0  1.7G   0% /dev
tmpfs           1.9G   20K  1.9G   1% /dev/shm
tmpfs           768M  1.2M  767M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
/dev/sda1       253M   51M  202M  20% /boot
tmpfs           384M     0  384M   0% /run/user/1001

Note: This is only available in PowerShell 7

$LASTEXITCODE

This is something to check if your script, or a command in your script, exited correctly with a zero as the exit code. If it differs, 1 indicates an error so you can act accordingly on that exit code. For example, you can ping a website using a Scheduled Task. If the script exits with 0, all is well. If it exits with 1, the script has failed to execute. But if the ping didn’t work or was stopped, the exit code is -1073741510, indicating it was stopped abruptly.

For example, below, I ping powershellisfun.com 4 times, and I do the same again, but CTRL-C / Stop is during pinging:

C:\> ping powershellisfun.com

Pinging powershellisfun.com [192.0.78.202] with 32 bytes of data:
Reply from 192.0.78.202: bytes=32 time=10ms TTL=57
Reply from 192.0.78.202: bytes=32 time=13ms TTL=57
Reply from 192.0.78.202: bytes=32 time=14ms TTL=57
Reply from 192.0.78.202: bytes=32 time=11ms TTL=57

Ping statistics for 192.0.78.202:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 10ms, Maximum = 14ms, Average = 12ms

C:\> $LASTEXITCODE
0


C:\> ping powershellisfun.com

Pinging powershellisfun.com [192.0.78.202] with 32 bytes of data:
Reply from 192.0.78.202: bytes=32 time=14ms TTL=57
Reply from 192.0.78.202: bytes=32 time=13ms TTL=57

Ping statistics for 192.0.78.202:
    Packets: Sent = 2, Received = 2, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 13ms, Maximum = 14ms, Average = 13ms
Control-C

C:\> $LASTEXITCODE
-1073741510

In a script, that would look like:

C:\> ping powershellisfun.com
>> if ($LASTEXITCODE -eq '-1073741510') {
>> Write-Warning ("Error occured")
>> }elseif ($LASTEXITCODE -eq '0'){
>> Write-Host ("No issues reaching powershellisfun.com") -ForegroundColor Green
>> }
>>

Pinging powershellisfun.com [192.0.78.202] with 32 bytes of data:
Reply from 192.0.78.202: bytes=32 time=10ms TTL=57
Reply from 192.0.78.202: bytes=32 time=13ms TTL=57
Reply from 192.0.78.202: bytes=32 time=12ms TTL=57
Reply from 192.0.78.202: bytes=32 time=11ms TTL=57

Ping statistics for 192.0.78.202:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 10ms, Maximum = 13ms, Average = 11ms

No issues reaching powershellisfun.com

$Profile

This is something I use a lot to edit my PowerShell profile quickly. It contains the full path to the current profile:

C:\> $profile
C:\Users\HarmVeenstra\OneDrive - NEXXT\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

This makes viewing it easy:

C:\> type $profile
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Import-Module Posh-Git
Set-PSReadlineKeyHandler -Key Tab -Function Complete
Import-Module -Name Terminal-Icons
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle ListView
Import-Module Az.Tools.Predictor
Set-PSReadLineOption -PredictionSource HistoryAndPlugin

$PSCulture

This shows the regional settings/culture of your PowerShell session:

C:\> $PSCulture
nl-NL

$PSCulture shows the Name property from the Get-Culture cmdlet:

C:\> Get-Culture

LCID             Name             DisplayName
----             ----             -----------
1043             nl-NL            Dutch (Netherlands)

$PSHome

This shows the directory that your current PowerShell session is started from:

C:\> $PSHOME
C:\Program Files\PowerShell\7

$PSUICulture

This shows the language setting of the UI of the operating system:

C:\> $PSUICulture
en-US

This can be used, just like $PSCulture, to use language-specific settings.

$PSVersionTable

This shows more detailed information than $Host:

C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.3.4
PSEdition                      Core
GitCommitId                    7.3.4
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

$true

This variable can be used to represent True in the script, but… I use it for looping things until I press CTRL-C. Easy to monitor things by letting a cmdlet run continuously. For example:

C:\> while ($true) {
>> $logcount=(Get-ChildItem -Path D:\Temp -Filter *.log).count
>> Write-host ("There are {0} logs in d:\temp" -f $logcount)
>> Start-Sleep -Seconds 30
>> }

There are 2 logs in d:\temp
There are 2 logs in d:\temp
There are 3 logs in d:\temp

In this example, the script counts the number of logs and waits 30 seconds to count them again. It outputs the number of logs found on the screen. For example, this is easy if you’re monitoring a folder for changes.

More information

You can find other examples on this Microsoft Learn page.

2 thoughts on “PowerShell Automatic Variables

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.