Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
May 20, 2025

PowerShell Automatic Variables

> I hope you've been working on last month's scripting challenge. I'll have a solution next week.

When using PowerShell, either in an interactive console session or in a script, you might want to take advantage of built-in or automatic variables. These variables are created and maintained by PowerShell, and they provide useful information about the current session, the state of the script or command execution, or the environment. You don't need to define them; they are automatically available for use. However, this also means that you should avoid using the variable names for your own variables.

PID

Some of the variables are defined as read-only or constant so you'll get an error if you try to use the variable name for your own variable. For example, if you try to assign a value to $PID, you'll get an error because $PID is a read-only variable that contains the process ID of the current PowerShell session.

PS S:\> $pid
35996
PS S:\> $pid = 4
WriteError: Cannot overwrite variable PID because it is read-only or constant.

I can use this variable to filter out the current pwsh process.

Get-Process pwsh -IncludeUserName | where id -ne $pid | Select ID,CommandLine,Username,StartTime,@{Name="Runtime";Expression = {New-TimeSpan -Start $_.startTime -end (Get-Date)}}
Using 6756
figure 1

$pecial

Don't forget that you only include the $ sign when you are referencing the variable. In the previous example the variable name is PID. We use $PID to reference the variable value.. If you want to use the variable in a string, you can use the $(...) syntax to reference the variable.

However, there is a variable with a name of $.

PS C:\> $$
0
PS C:\> Get-Variable -Name $

Name                           Value
----                           -----
$                              0

The variable holds the last token of the last processed command. PowerShell uses the AST (Abstract Syntax Tree) to parse the command. This breaks a command down into its components using tokens. The $ variable shows you the last token. If you are familiar with regular expressions, the $ is used to indicate a pattern at the end of a string. The principal is the same.

PS C:\> Get-Service bits

Status   Name               DisplayName
------   ----               -----------
Stopped  bits               Background Intelligent Transfer Service

PS C:\> $$
bits
PS C:\> 1..5 | Foreach-Object { ($_*$_) * 3.14}
3.14
12.56
28.26
50.24
78.5
PS C:\> $$
}

Don't confuse token with character. In this example the tokens are bits and }. I don't have a good practical example for this variable, and I rarely write code that relies on the AST.

$^

The counterpart to $ is the ^ variable. This variable holds the first token of the last processed command.

PS C:\> Get-Service bits

Status   Name               DisplayName
------   ----               -----------
Stopped  bits               Background Intelligent Transfer Servi…

PS C:\> $^
Get-Service

Again, I don't have a good practical example for this variable. If you have a use case for $^ or $$, I'd love to hear about it.

$?

The ? variable is a boolean value that indicates whether the last command was successful. If the last command was successful, $? is True. If the last command failed, $? is False. The command has to properly complete for this variable to be set. If you mangle the syntax, the command won't run so the variable remains unchanged.

PS C:\> Get-Service winrm

Status   Name               DisplayName
------   ----               -----------
Running  winrm              Windows Remote Management (WS-Management)

PS C:\> $?
True
PS C:\> Get-Service abcdef
Get-Service: Cannot find any service with service name 'abcdef'.
PS C:\> $?
False

> *Don't confuse this variable with the ? alias for Where-Object.

This should also apply to native commands, i.e. non-PowerShell commands.

PS C:\Scripts\PSTeachingTools> $?
True
PS C:\Scripts\PSTeachingTools> cd c:\temp
PS C:\temp> git status
fatal: not a git repository (or any of the parent directories): .git
PS C:\temp> $?
False
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.