PowerShell: Variables and Data Types
Variables are containers for storing data in your scripts. PowerShell is dynamically typed but provides strong typing when needed. This lesson covers variable declaration, scoping, data types, arrays, hashtables, and custom objects - essential for writing powerful scripts.
What You'll Learn
- Creating and using variables
- Variable naming conventions
- Data types
- Type conversion and casting
- Arrays and array operations
- Hashtables (dictionaries)
- Custom objects (PSCustomObject)
- Variable scope
- Environment variables
Creating Variables
Basic Declaration
# Simple assignment ($ prefix)
$name = "Alice"
$age = 25
$isAdmin = $true
$price = 19.99
# No type declaration needed!
$var = "string"
$var = 123 # Now it's a number
$var = $true # Now it's a boolean
Variable Naming Rules
✓ Must start with $
✓ Can contain letters, numbers, underscores
✓ Case-insensitive ($Name = $name = $NAME)
✓ Use descriptive names
Examples:
$userName
$user_name
$userName123
$_private
Data Types
Common Types
# String
$text = "Hello, World!"
$text.GetType().Name # String
# Integer
$number = 42
$number.GetType().Name # Int32
# Double (decimal)
$price = 19.99
$price.GetType().Name # Double
# Boolean
$isActive = $true
$isActive.GetType().Name # Boolean
# DateTime
$date = Get-Date
$date.GetType().Name # DateTime
# Array
$array = @(1, 2, 3)
$array.GetType().Name # Object[]
# Hashtable
$hash = @{Name="Alice"; Age=25}
$hash.GetType().Name # Hashtable
Check Variable Type
$var = 42
# Method 1
$var.GetType()
# Method 2
$var -is [int] # True
$var -is [string] # False
# Get type name
$var.GetType().Name # Int32
$var.GetType().FullName # System.Int32
Type Conversion and Casting
Explicit Casting
# Cast to specific type
[int]$number = "42" # String to Int
[string]$text = 123 # Int to String
[double]$decimal = 10 # Int to Double
[datetime]$date = "2025-10-08" # String to DateTime
# Type enforcement
[int]$age = 25
$age = "thirty" # ERROR! Type mismatch
Implicit Conversion
# PowerShell converts automatically
$result = "10" + 20 # 1020 (string concatenation)
$result = 10 + "20" # 30 (numeric addition)
# Be careful!
"5" + 10 # "510" (string)
5 + "10" # 15 (number)
Convert Methods
# Convert strings to numbers
[Convert]::ToInt32("42")
[Convert]::ToDouble("3.14")
# Convert to specific types
[int]::Parse("123")
[double]::Parse("3.14")
[datetime]::Parse("2025-10-08")
# Try parse (safer)
$result = 0
if ([int]::TryParse("123", [ref]$result)) {
Write-Host "Parsed: $result"
} else {
Write-Host "Failed to parse"
}
Arrays
Creating Arrays
# Method 1: @() syntax
$array = @(1, 2, 3, 4, 5)
# Method 2: Comma operator
$array = 1, 2, 3, 4, 5
# Method 3: Range operator
$array = 1..10 # 1 to 10
# Empty array
$empty = @()
# Single item array
$single = ,1 # Force single item array
$single = @(1) # Alternative
Accessing Elements
$array = @("a", "b", "c", "d", "e")
# By index (0-based)
$array[0] # "a"
$array[2] # "c"
$array[-1] # "e" (last item)
$array[-2] # "d" (second to last)
# Range
$array[0..2] # a, b, c
$array[1..3] # b, c, d
# Multiple specific indices
$array[0,2,4] # a, c, e
# Array length
$array.Length # 5
$array.Count # 5
Array Operations
# Add element (creates new array)
$array = @(1, 2, 3)
$array += 4 # 1, 2, 3, 4
# Add multiple
$array += 5, 6, 7
# Combine arrays
$a = @(1, 2)
$b = @(3, 4)
$c = $a + $b # 1, 2, 3, 4
# Remove element (filter)
$array = @(1, 2, 3, 4, 5)
$array = $array | Where-Object { $_ -ne 3 } # Remove 3
# Check if contains
$array -contains 3 # True/False
3 -in $array # True/False
# Sort
$array | Sort-Object
$array | Sort-Object -Descending
# Unique values
$array | Select-Object -Unique
Array Methods
$array = @(3, 1, 4, 1, 5, 9, 2, 6)
# Sort (modifies original)
$array.Sort()
# Reverse (modifies original)
$array.Reverse()
# Index of value
$array.IndexOf(4)
# Clear array
$array.Clear()
ArrayList (Resizable)
# Create ArrayList
$list = New-Object System.Collections.ArrayList
# Add items
$list.Add("item1") | Out-Null
$list.Add("item2") | Out-Null
$list.AddRange(@("item3", "item4"))
# Remove items
$list.Remove("item2")
$list.RemoveAt(0) # Remove by index
# Access
$list[0]
$list.Count
Hashtables
Creating Hashtables
# Method 1: @{} syntax
$user = @{
Name = "Alice"
Age = 25
City = "NYC"
}
# Method 2: Explicit
$hash = @{}
$hash["key1"] = "value1"
$hash["key2"] = "value2"
# Ordered hashtable
$ordered = [ordered]@{
First = 1
Second = 2
Third = 3
}
Accessing Hashtable
$user = @{Name="Alice"; Age=25; City="NYC"}
# Access by key
$user["Name"] # Alice
$user.Name # Alice (dot notation)
# Add key-value
$user["Email"] = "[email protected]"
$user.Phone = "555-1234"
# Update value
$user["Age"] = 26
$user.Age = 26
# Remove key
$user.Remove("City")
# Check if key exists
$user.ContainsKey("Name") # True
$user.ContainsKey("Phone") # True/False
Hashtable Operations
$hash = @{A=1; B=2; C=3}
# Get keys
$hash.Keys
# Get values
$hash.Values
# Count items
$hash.Count
# Loop through hashtable
foreach ($key in $hash.Keys) {
Write-Host "$key = $($hash[$key])"
}
# Alternative loop
$hash.GetEnumerator() | ForEach-Object {
Write-Host "$($_.Key) = $($_.Value)"
}
Custom Objects (PSCustomObject)
Creating Custom Objects
# Method 1: PSCustomObject
$user = [PSCustomObject]@{
Name = "Alice"
Age = 25
City = "NYC"
}
# Method 2: New-Object
$user = New-Object PSObject -Property @{
Name = "Bob"
Age = 30
City = "LA"
}
# Access properties
$user.Name # Alice
$user.Age # 25
# Add property
$user | Add-Member -MemberType NoteProperty -Name "Email" -Value "[email protected]"
# Modify property
$user.Age = 26
Working with Objects
# Create multiple objects
$users = @(
[PSCustomObject]@{Name="Alice"; Age=25; City="NYC"}
[PSCustomObject]@{Name="Bob"; Age=30; City="LA"}
[PSCustomObject]@{Name="Charlie"; Age=35; City="Chicago"}
)
# Access objects
$users[0].Name # Alice
$users[1].Age # 30
# Filter objects
$users | Where-Object { $_.Age -gt 25 }
# Select properties
$users | Select-Object Name, Age
# Export to CSV
$users | Export-Csv users.csv -NoTypeInformation
# Convert to JSON
$users | ConvertTo-Json
Variable Scope
Scope Levels
Global: Available everywhere
Script: Available in script file
Local: Current scope (default)
Private: Current scope only (not child scopes)
Scope Examples
# Global variable
$global:name = "Alice"
# Script variable
$script:age = 25
# Local variable (default)
$city = "NYC"
# Private variable
$private:secret = "password"
# Access from different scopes
function Test {
Write-Host $global:name # Accessible
Write-Host $script:age # Accessible
Write-Host $city # May not be accessible
}
Special Variables
Automatic Variables
$_ # Current pipeline object
$? # Success of last command (True/False)
$^ # First token of last command
$$$ # Last token of last command
$LASTEXITCODE # Exit code of last program
$Error # Array of recent errors
$Host # Host application info
$HOME # User home directory
$PSVersionTable # PowerShell version info
$PWD # Current directory
$null # Null value
$true # Boolean true
$false # Boolean false
Examples:
# Check if command succeeded
Remove-Item file.txt
if ($?) {
Write-Host "Success"
} else {
Write-Host "Failed"
}
# Get last error
$Error[0]
# Current user home
Write-Host $HOME
# PowerShell version
$PSVersionTable.PSVersion
Environment Variables
Access Environment Variables
# Method 1: $env: prefix
$env:USERNAME
$env:COMPUTERNAME
$env:PATH
$env:TEMP
# Method 2: [Environment] class
[Environment]::GetEnvironmentVariable("USERNAME")
# List all environment variables
Get-ChildItem Env:
# Check if exists
Test-Path Env:\USERNAME
Set Environment Variables
# Current session only
$env:MY_VAR = "value"
# Permanent (user level)
[Environment]::SetEnvironmentVariable("MY_VAR", "value", "User")
# Permanent (system level) - requires admin
[Environment]::SetEnvironmentVariable("MY_VAR", "value", "Machine")
# Remove
[Environment]::SetEnvironmentVariable("MY_VAR", $null, "User")
Practical Examples
Example 1: User Information Object
$user = [PSCustomObject]@{
Username = $env:USERNAME
ComputerName = $env:COMPUTERNAME
Domain = $env:USERDOMAIN
HomeDir = $env:USERPROFILE
IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
$user | Format-List
Example 2: Configuration Hashtable
$config = @{
Target = "192.168.1.100"
Ports = @(80, 443, 445, 3389)
Timeout = 5
Threads = 10
Output = "results.txt"
}
# Use config
Write-Host "Scanning $($config.Target)..."
foreach ($port in $config.Ports) {
# Scan port
}
Example 3: Process Collection
$processes = Get-Process | Where-Object { $_.CPU -gt 10 } | ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
PID = $_.Id
CPU = [math]::Round($_.CPU, 2)
Memory = [math]::Round($_.WorkingSet / 1MB, 2)
}
}
$processes | Export-Csv high_cpu.csv -NoTypeInformation
Practical Pentesting Scenarios
Scenario 1: Target List Management
$targets = @(
[PSCustomObject]@{IP="192.168.1.1"; Name="Router"; Status="Unknown"}
[PSCustomObject]@{IP="192.168.1.100"; Name="Server1"; Status="Unknown"}
[PSCustomObject]@{IP="192.168.1.101"; Name="Server2"; Status="Unknown"}
)
foreach ($target in $targets) {
if (Test-Connection -ComputerName $target.IP -Count 1 -Quiet) {
$target.Status = "Online"
} else {
$target.Status = "Offline"
}
}
$targets | Format-Table
Scenario 2: Scan Results Storage
$scanResults = @{}
$ports = @(21, 22, 80, 443, 445, 3389)
foreach ($port in $ports) {
$result = Test-NetConnection -ComputerName $target -Port $port -WarningAction SilentlyContinue
$scanResults[$port] = $result.TcpTestSucceeded
}
# Display results
$scanResults.GetEnumerator() | ForEach-Object {
$status = if ($_.Value) { "OPEN" } else { "CLOSED" }
Write-Host "Port $($_.Key): $status"
}
Scenario 3: Credential Storage
$credentials = @(
@{Username="admin"; Password="password123"; Status="Untested"}
@{Username="root"; Password="toor"; Status="Untested"}
@{Username="admin"; Password="admin"; Status="Untested"}
)
foreach ($cred in $credentials) {
# Test credential (pseudocode)
$valid = Test-Credential -User $cred.Username -Pass $cred.Password
$cred.Status = if ($valid) { "Valid" } else { "Invalid" }
}
$credentials | Format-Table
Quick Reference
Variables:
$name = "value"
$var.GetType()
$var -is [type]
Arrays:
$arr = @(1, 2, 3)
$arr = 1..10
$arr[0]
$arr[-1]
$arr.Count
$arr += 4
Hashtables:
$hash = @{Key="Value"}
$hash["Key"]
$hash.Key
$hash.Keys
$hash.Values
$hash.ContainsKey("Key")
Custom Objects:
$obj = [PSCustomObject]@{Name="Alice"; Age=25}
$obj.Name
$obj | Add-Member -Name "City" -Value "NYC" -MemberType NoteProperty
Scope:
$global:var
$script:var
$local:var
$private:var
Environment:
$env:USERNAME
$env:PATH
[Environment]::GetEnvironmentVariable("VAR")
Resources
Help
Get-Help about_Variables
Get-Help about_Arrays
Get-Help about_Hash_Tables
Get-Help about_Scopes
Next Steps
- Practice with arrays - master array operations
- Use hashtables for configuration
- Create custom objects for structured data
- Understand scope - avoid variable conflicts
- Master environment variables for system info
Variables are the foundation of every script. Master these concepts and you'll write clean, powerful PowerShell code!
"$variables: Because remembering everything is hard."