Free Ebook cover Windows PowerShell for Beginners: Everyday Automation and System Insights

Windows PowerShell for Beginners: Everyday Automation and System Insights

New course

10 pages

Variables and Simple Logic: Building Blocks for Everyday Automation

Capítulo 8

Estimated reading time: 6 minutes

+ Exercise

Why Variables Matter in Everyday Automation

Automation usually follows a simple pattern: get some information, store it, make a decision, then act. Variables are how you store information so you can reuse it later in the script without re-running commands or retyping values.

In PowerShell, variables start with $. Use meaningful names so your future self (or a teammate) can understand what the script is doing at a glance.

$computerName = $env:COMPUTERNAME
$logFolder    = 'C:\Logs'
$maxSizeMB     = 200

Notice the consistent indentation and alignment. You do not have to align assignments, but consistency improves readability.

Basic Data Types You’ll Use All the Time

Strings

Strings are text values. Use single quotes for literal text and double quotes when you want variable expansion.

$literalPath = 'C:\Temp\Reports'
$userPath    = "C:\Users\$env:USERNAME\Desktop"

Integers (numbers)

Numbers are used for counts, thresholds, and comparisons.

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

$retryCount = 3
$timeoutSec = 30

Booleans

Booleans are $true or $false. They’re often the result of a test, or used as flags.

$isDryRun = $true  # set to $false to actually perform changes

Dates and times

Dates are useful for timestamps and age checks.

$now = Get-Date
$cutoff = (Get-Date).AddDays(-7)

Quick type awareness

You can inspect a value’s type when you’re unsure what you’re working with.

$now.GetType().FullName

Storing Command Results in Variables

A common pattern is to run a command once, store the result, then use it multiple times.

Example: Capture a service and act on it

Step-by-step:

  • Store the service object in a variable.
  • Check its current status.
  • Only take action if needed.
$serviceName = 'Spooler'
$service     = Get-Service -Name $serviceName

if ($service.Status -ne 'Running') {
    # Start only if not already running
    Start-Service -Name $serviceName
}

This avoids unnecessary actions and makes the script safe to run repeatedly.

Example: Store a list of items from a command

When a command returns multiple objects, the variable holds a collection.

$stoppedServices = Get-Service | Where-Object Status -eq 'Stopped'

$stoppedServices.Count

Storing the result lets you reuse it (for counting, reporting, or taking action) without re-running the query.

Arrays: Iterating Over Multiple Items

An array is an ordered list. Use arrays when you have “a bunch of similar things” to process: computer names, folders, service names, file extensions, etc.

Create an array

$foldersToCheck = @(
    'C:\Temp',
    'C:\Logs',
    'C:\Tools'
)

Loop through items with foreach

Step-by-step:

  • Define the list.
  • Iterate over each item.
  • Run the same logic for each.
$foldersToCheck = @('C:\Temp', 'C:\Logs', 'C:\Tools')

foreach ($folder in $foldersToCheck) {
    Write-Host "Checking: $folder"
}

Use a singular loop variable name ($folder) for a plural collection ($foldersToCheck). This small naming habit improves readability.

Common pattern: Check whether a path exists before creating it

This is one of the most practical if/else patterns in PowerShell.

$targetFolder = 'C:\Logs\App1'

if (-not (Test-Path -Path $targetFolder)) {
    # Create the folder only if it does not exist
    New-Item -Path $targetFolder -ItemType Directory | Out-Null
}

Test-Path returns a boolean. The -not flips it, so the block runs only when the folder is missing.

Combine arrays + path checks

$foldersToEnsure = @(
    'C:\Logs\App1',
    'C:\Logs\App2',
    'C:\Logs\App3'
)

foreach ($folder in $foldersToEnsure) {
    if (-not (Test-Path -Path $folder)) {
        New-Item -Path $folder -ItemType Directory | Out-Null
    }
}

Hashtables: Simple, Readable “Key = Value” Data

A hashtable stores pairs: a key and its value. Use it when you want to label values (instead of relying on array positions) or when you want quick lookups.

Create and read a hashtable

$settings = @{
    LogRoot     = 'C:\Logs\App1'
    MaxSizeMB   = 200
    RetainDays  = 14
    EnableDebug = $false
}

$settings.LogRoot
$settings['MaxSizeMB']

Dot notation is convenient for simple keys. Bracket notation is useful when keys contain spaces or special characters.

Example: Use a hashtable to drive decisions

Step-by-step:

  • Define settings once.
  • Use them in conditions.
  • Act only when conditions are met.
$settings = @{
    LogRoot    = 'C:\Logs\App1'
    MaxSizeMB  = 200
    RetainDays = 14
}

if (-not (Test-Path -Path $settings.LogRoot)) {
    New-Item -Path $settings.LogRoot -ItemType Directory | Out-Null
}

Simple Logic with if/elseif/else

Conditional logic lets your script make decisions instead of doing the same thing every time. PowerShell conditions evaluate to $true or $false.

Basic if/else

$freeGB = 12

if ($freeGB -lt 10) {
    Write-Host 'Low disk space: take action'
}
else {
    Write-Host 'Disk space looks OK'
}

Multiple branches with elseif

$cpuLoad = 85

if ($cpuLoad -ge 90) {
    Write-Host 'CPU load is critical'
}
elseif ($cpuLoad -ge 75) {
    Write-Host 'CPU load is elevated'
}
else {
    Write-Host 'CPU load is normal'
}

Common comparison operators

OperatorMeaningExample
-eqequals$x -eq 5
-nenot equals$status -ne 'Running'
-ltless than$n -lt 10
-leless than or equal$n -le 10
-gtgreater than$n -gt 10
-gegreater than or equal$n -ge 10
-likewildcard match$name -like 'SQL*'
-matchregex match$text -match '^ERR'

Act Only When a Condition Is Met

Many automation tasks should be “no-op” when there’s nothing to do. This makes scripts safe to run on a schedule.

Example: Only create a folder when missing (with a message)

$targetFolder = 'C:\Temp\Daily'

if (Test-Path -Path $targetFolder) {
    Write-Host "Already exists: $targetFolder"
}
else {
    New-Item -Path $targetFolder -ItemType Directory | Out-Null
    Write-Host "Created: $targetFolder"
}

Example: Only stop a service if it’s running

$serviceName = 'wuauserv'
$service = Get-Service -Name $serviceName

if ($service.Status -eq 'Running') {
    # Stop only when running
    Stop-Service -Name $serviceName
}

Example: Guard clauses to keep code readable

A guard clause exits early when a requirement isn’t met. This can reduce nesting and keep scripts easier to scan.

$sourceFolder = 'C:\Temp\Input'

if (-not (Test-Path -Path $sourceFolder)) {
    Write-Host "Source folder missing: $sourceFolder"
    return
}

# Continue only when the folder exists
Write-Host "Processing files in: $sourceFolder"

Readable Code: Naming, Indentation, and Comments

Meaningful variable names

Prefer descriptive names over short ones. Compare:

# Harder to read
$x = 'C:\Logs'
$y = 14

# Easier to read
$logRootPath = 'C:\Logs'
$retainDays  = 14

Consistent indentation

Indent inside if, foreach, and other blocks. Avoid mixing styles within the same script.

foreach ($folder in $foldersToEnsure) {
    if (-not (Test-Path -Path $folder)) {
        New-Item -Path $folder -ItemType Directory | Out-Null
    }
}

Brief comments that explain “why”

Comments are most valuable when they explain intent or constraints, not when they restate the obvious.

$archiveFolder = 'C:\Logs\Archive'

# Keep archives separate so cleanup jobs can target one location
if (-not (Test-Path -Path $archiveFolder)) {
    New-Item -Path $archiveFolder -ItemType Directory | Out-Null
}

Mini-Recipe: A Small, Practical Automation Script

This example combines variables, arrays, hashtables, looping, and if/else into a single purpose-driven task: ensure folders exist and apply simple rules per folder.

Step-by-step:

  • Define folder rules in a hashtable.
  • Loop through each rule.
  • Create missing folders.
  • Print a message only when an action is taken.
$folderRules = @{
    'C:\Logs\App1' = @{ Ensure = $true;  Note = 'Main app logs' }
    'C:\Logs\App2' = @{ Ensure = $true;  Note = 'Secondary app logs' }
    'C:\Logs\Old'  = @{ Ensure = $false; Note = 'Deprecated location' }
}

foreach ($path in $folderRules.Keys) {
    $rule = $folderRules[$path]

    if (-not $rule.Ensure) {
        # Skip paths that are intentionally not managed
        continue
    }

    if (-not (Test-Path -Path $path)) {
        New-Item -Path $path -ItemType Directory | Out-Null
        Write-Host "Created folder: $path ($($rule.Note))"
    }
}

Now answer the exercise about the content:

In a PowerShell script that should be safe to run repeatedly, which approach best ensures a folder is created only when it’s missing?

You are right! Congratulations, now go to the next page

You missed! Try again.

Checking with Test-Path and creating the folder only when the test is false avoids unnecessary actions, making the script safe to run repeatedly.

Next chapter

Writing Your First PowerShell Scripts: From One-Liners to Reusable Tools

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.