Skip to main content

PowerShell Variables: Complete Guide with Types, Scoping & Examples [2024]

5 min read
powershell variables basics data types scoping windows

Master PowerShell variables—the foundation of all scripts. This comprehensive guide covers data types, scoping rules, expansion techniques, special variables, and production-grade patterns.

Table of Contents

  1. What are Variables?
  2. Variable Naming Rules
  3. Variable Types
  4. Strings vs Variable Expansion
  5. Numeric Variables
  6. Boolean Variables
  7. Array Variables
  8. Hashtable Variables
  9. Object Variables
  10. Special Variables
  11. Variable Scope
  12. Casting & Type Conversion
  13. Read-Only Variables
  14. Variable Operations
  15. Common Mistakes
  16. Best Practices
  17. Troubleshooting
  18. FAQs
  19. Real-World Examples
  20. Conclusion

What are Variables? {#what-are-variables}

A PowerShell variable is a named storage location that holds a value. Variables are fundamental building blocks—they store data, cmdlet output, calculations, and object references.

Key Characteristics:

  • ✅ Dynamically typed (type determined at assignment)
  • ✅ Case-insensitive by default (best practice: follow conventions)
  • ✅ Prefixed with dollar sign $
  • ✅ Can hold any .NET data type
  • ✅ Scoped (local, script, global, environment)
  • ✅ Can be cast to specific types

Variable Naming Rules {#naming-rules}

Valid Names

$number = 42
$name = "John"
$serverList = @("Server1", "Server2")
$_currentValue = "Value"
$result2024 = "Data"

Invalid Names

$-number = 42        # ❌ Special char at start
$123start = 42       # ❌ Can't start with number
$my-var = 42         # ❌ Hyphens invalid (use camelCase)
$ space = 42         # ❌ Spaces invalid

Naming Best Practices

  • Use camelCase: $serverName, $processCount
  • Use descriptive names: $user not $u
  • Avoid single letters except in loops: foreach ($item in $items)
  • Use plural for collections: $services, $users

Variable Types {#types}

TypeExampleDescription
[string]$name = "John"Text values
[int]$count = 42Whole numbers
[double]$price = 19.99Decimal numbers
[boolean]$enabled = $trueTrue/False
[array]$items = @(1, 2, 3)Collections
[hashtable]$config = @{...}Key-value pairs
[PSCustomObject][PSCustomObject]@{...}Custom objects
[DateTime][DateTime]::NowDates and times

Strings vs Variable Expansion {#expansion}

Single Quotes (Literal - No Expansion)

$name = "John"
Write-Output 'Hello $name'     # Output: Hello $name
Write-Output 'Value is $5.00'  # Output: Value is $5.00

Double Quotes (Interpolation - Expansion)

$name = "John"
Write-Output "Hello $name"     # Output: Hello John
Write-Output "2 + 2 = $((2 + 2))"  # Output: 2 + 2 = 4

Property Access in Strings

$file = Get-Item -Path "C:\test.txt"
Write-Output "File: $($file.Name)"        # Output: File: test.txt
Write-Output "Modified: $($file.LastWriteTime.ToString('yyyy-MM-dd'))"

Numeric Variables {#numeric}

Integer Variables

[int]$count = 100
$count++
Write-Output "Count: $count"  # Output: Count: 101

# Automatic type detection
$num = 42                      # Becomes [int]
$num = 42.5                    # Becomes [double]

Double/Decimal Variables

[double]$pi = 3.14159
$price = 19.99                 # Automatic double

# Math operations
$total = $price * 2
$average = ($count1 + $count2) / 2

Rounding and Formatting

$value = 3.14159
[Math]::Round($value, 2)      # Output: 3.14
"{0:F2}" -f $value            # Output: 3.14

Boolean Variables {#boolean}

True/False Values

$enabled = $true
$isAdmin = $false

if ($enabled) {
    Write-Output "Feature is enabled"
}

# Negation
if (-not $isAdmin) {
    Write-Output "User is not admin"
}

Converting to Boolean

[bool]"true"          # $true
[bool]"false"         # $true (any non-empty string is $true!)
[bool]0               # $false
[bool]1               # $true

Array Variables {#array-variables}

Creating Arrays

# Using @() operator
$numbers = @(1, 2, 3, 4, 5)
$names = @("Alice", "Bob", "Charlie")

# Implicit array
$colors = "red", "green", "blue"

# Empty array
$empty = @()

Accessing Array Elements

$services = @("BITS", "wuauserv", "WinDefend")

$services[0]           # First: BITS
$services[-1]          # Last: WinDefend
$services[0, 2]        # Multiple: BITS, WinDefend
$services[1..2]        # Range: wuauserv, WinDefend

Array Operations

$list = @(1, 2, 3)

# Add item
$list += 4

# Count items
$list.Count            # 4

# Loop
foreach ($item in $list) { Write-Output $item }

# Filter
$list | Where-Object { $_ -gt 2 }

Hashtable Variables {#hashtable-variables}

Creating Hashtables

# Using @{} syntax
$config = @{
    Server = "localhost"
    Port = 8080
    Debug = $true
}

# Accessing values
$config["Server"]      # localhost
$config.Port           # 8080

Modifying Hashtables

$user = @{
    Name = "John"
    Age = 30
}

# Add new key
$user["Email"] = "john@example.com"

# Update existing
$user.Age = 31

# Remove key
$user.Remove("Age")

Object Variables {#object-variables}

Creating Custom Objects

$person = [PSCustomObject]@{
    Name = "John"
    Age = 30
    Department = "IT"
}

# Access properties
$person.Name           # John
$person["Age"]         # 30

# Modify properties
$person.Age = 31

Collections of Objects

$users = @(
    [PSCustomObject]@{Name = "John"; Age = 30},
    [PSCustomObject]@{Name = "Jane"; Age = 28},
    [PSCustomObject]@{Name = "Bob"; Age = 35}
)

# Filter objects
$users | Where-Object { $_.Age -gt 30 }

# Get properties
$users | Select-Object -ExpandProperty Name

Special Variables {#special}

VariableMeaningExample
$_Current pipeline objectGet-Service | ForEach-Object { $_.Name }
$argsScript argumentsAccess function parameters
$nullNo value$x = $null
$trueBoolean trueif ($enabled)
$falseBoolean falseif (-not $disabled)
$?Last command successif ($?) { "Success" }
$LASTEXITCODELast command exit codeExternal program results
$HostPowerShell host$Host.UI.WriteErrorLine()
$PSVersionTablePowerShell version$PSVersionTable.PSVersion
$env:Environment variables$env:USERNAME, $env:APPDATA

Using $env Variables

$username = $env:USERNAME          # Current user
$computerName = $env:COMPUTERNAME  # Computer name
$tempPath = $env:TEMP              # Temp directory

# Modify environment variable
$env:CUSTOMVAR = "MyValue"

Variable Scope {#scope}

Local Scope (Default)

$globalVar = "I'm global"

function Test-Local {
    $localVar = "I'm local"
    Write-Output $globalVar   # Can access global
}

Test-Local
Write-Output $localVar        # Error: $localVar doesn't exist here

Script Scope

$script:sharedVar = "Shared across script"

function Modify {
    $script:sharedVar = "Modified"
}

Modify
Write-Output $script:sharedVar  # Modified

Global Scope

$global:globalVar = "Truly global"

function Access {
    Write-Output $global:globalVar
}

Access

Casting & Type Conversion {#casting}

Explicit Casting

[string]$text = 42                # "42"
[int]$number = "100"              # 100
[double]$decimal = "3.14"         # 3.14
[bool]$flag = 1                   # $true
[datetime]$date = "2024-02-05"    # Date object

# Array casting
[string[]]$names = "Alice", "Bob"

Parsing vs Casting

# Safe parsing with try-catch
try {
    $num = [int]::Parse("123")
} catch {
    Write-Error "Invalid number"
}

# Direct casting (throws error on failure)
$num = [int]"456"               # Works
$num = [int]"not-a-number"      # Error!

Read-Only Variables {#readonly}

Creating Read-Only Variables

$readOnly = "Initial value"
Set-Variable -Name readOnly -Value "New value" -Option ReadOnly

# Now this will error:
$readOnly = "Cannot change"     # Error: Variable is read-only

Constant Variables

Set-Variable -Name PI -Value 3.14159 -Option Constant

# Cannot be changed, even with Set-Variable
Set-Variable -Name PI -Value 3.14  # Error!

Variable Operations {#operations}

Testing Variables

# Test if exists
if (Test-Path Variable:myVar) { Write-Output "Exists" }

# Get variable value
$value = Get-Variable -Name myVar -ValueOnly

# List all variables
Get-Variable | Where-Object { $_.Name -like "my*" }

Clearing Variables

# Remove single variable
Remove-Variable -Name myVar

# Remove all user variables (keeps system variables)
Remove-Variable -Name * -ErrorAction SilentlyContinue

Common Mistakes {#mistakes}

❌ Mistake 1: Forgetting Dollar Sign

# WRONG: No $ prefix
name = "John"          # Error or creates new command

# RIGHT: Use $ prefix
$name = "John"         # Correct

❌ Mistake 2: Spaces Around Operators

# WRONG: Spaces cause issues
$x= 5                  # May not work as expected
$y =10                 # Inconsistent

# RIGHT: Consistent spacing
$x = 5
$y = 10

❌ Mistake 3: String Expansion Surprises

# WRONG: Expects expansion, won't happen
$path = 'C:\Users\$env:USERNAME\Documents'

# RIGHT: Use double quotes for expansion
$path = "C:\Users\$env:USERNAME\Documents"

❌ Mistake 4: Null Handling

# WRONG: Doesn't check for null
$data = Get-Item -Path "nonexistent" -ErrorAction SilentlyContinue
Write-Output $data.Name  # Error if null!

# RIGHT: Check before use
if ($data) { Write-Output $data.Name }

Best Practices {#best-practices}

Use Descriptive Names

  • $serverName not $s
  • $processCount not $pc

Type Hints When Appropriate

  • [string]$username = "admin"
  • [int]$port = 8080

Initialize Before Use

  • $total = 0 before $total += $value

Use Variable Scope Explicitly

  • $script:shared for script scope
  • $global:everywhere for global

Validate Input

  • Check for $null
  • Validate type with GetType()

Troubleshooting {#troubleshooting}

Issue: “Cannot find variable”

  • Cause: Typo or scope issue
  • Solution: Check spelling, use proper scope prefix

Issue: “Variable is read-only”

  • Cause: Variable was set with ReadOnly option
  • Solution: Create new variable or use Set-Variable -Force

Issue: String not expanding

  • Cause: Using single quotes
  • Solution: Use double quotes for interpolation

FAQs {#faqs}

Q: Are PowerShell variables case-sensitive?

A: Variables are case-insensitive (​$name = $NAME), but best practice is consistent casing.

Q: What’s the difference between $null and empty string?

A: $null = no value, "" = empty string

Q: Can I use hyphens in variable names?

A: No. Use $variable-name wrapping or camelCase: $variableName

Q: How do I clear all variables?

A: Remove-Variable -Name * -ErrorAction SilentlyContinue (preserves system variables)


Real-World Examples {#real-world-examples}

Example 1: Configuration Management

$config = @{
    DatabaseServer = "db.contoso.com"
    DatabasePort = 5432
    Username = "admin"
    Debug = $false
}

$connectionString = "Server=$($config.DatabaseServer);Port=$($config.DatabasePort)"

Example 2: Data Processing

$users = @(
    [PSCustomObject]@{Name = "John"; Department = "IT"},
    [PSCustomObject]@{Name = "Jane"; Department = "HR"}
)

$itUsers = $users | Where-Object { $_.Department -eq "IT" }

Example 3: Logging

$logFile = "C:\Logs\app_$(Get-Date -Format 'yyyyMMdd').log"
$logLevel = "INFO"
$message = "Application started"

"[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] [$logLevel] $message" | Add-Content -Path $logFile

Conclusion

PowerShell variables are fundamental to every script. Understanding types, scoping, and best practices enables you to write robust, maintainable automation.

Key Takeaways:

  • Variables store any .NET data type
  • Use clear naming conventions
  • Understand variable scope
  • Double quotes for string expansion, single quotes for literals
  • Always validate input and handle null values

For related concepts, explore PowerShell Arrays, PowerShell Hashtables, and the Complete PowerShell Guide.


Variable Types & Structures

  • PowerShell Arrays - Array variables and indexing
  • PowerShell Hashtables - Key-value variable storage
  • PowerShell Collections - Collection types
  • Custom Objects - Object variables
  • Type Casting - Convert variable types

Variable Scoping & Management

  • Variable Scope - Scope rules and inheritance
  • Environment Variables - System variables
  • Remove Environment Variable - Delete environment vars
  • Boolean Variables - True/false variables

String & Data Processing

  • PowerShell Strings - String variable operations
  • String Formatting - Format string variables
  • Null Values - Handle null variables
  • Numeric Operations - Math with variables

Control & Execution

Advanced Usage

  • PowerShell Operators - Operator variables
  • Regular Expressions - Regex with variables
  • PowerShell Remoting - Remote variables
  • Date/Time Variables - Date variables

Comprehensive Guides

  • Complete PowerShell Guide - Full variables section
  • Active Directory Guide - Variables in AD automation
  • PowerShell Best Practices - Variable naming conventions