Programming Fundamentals with PowerShell

In this post, I go over the fundamentals of programming using PowerShell and demonstrate why it's a great way to learn to code

8 months ago   •   15 min read

By 0xBEN
Table of contents

If you haven't already done so, check out my post on why PowerShell makes a great first programming language. This is a follow up post to that one.

PowerShell as Your First Programming Language
In this post, I discuss why PowerShell makes a great first programming language

The Syllabus

  • Visual Studio Code (VS Code)
  • Navigating the File System
  • Variables
  • Data Types
  • Arrays
  • Operators
  • Functions
  • Control Flow
  • Loops




Visual Studio Code

Installing Visual Studio Code

Follow this guide and get Visual Studio Code installed on your system.

Set up Visual Studio Code
Download and learn the basics of Visual Studio Code.

Install the PowerShell Extension

Installing this extension will allow VS Code to run and debug your code.
Click the Extensions marketplace icon

Install the official PowerShell extension





Navigating the File System

You should be comfortable navigating your way around the file system in the terminal in order to be a confident programmer. At a minimum, the ability to move around the file system and create, copy, move, and delete files and directories (folders) is an absolute requirement.

You are probably used to seeing a view such as this:

I have open in my Windows Explorer GUI the C:\Users\Test\Desktop\Test Folder directory. Inside of this directory, there are:

  • Directories
    • folder1
    • folder2
    • folder3
  • Files
    • file1.txt
    • file2.txt
    • file3.txt

In a typical GUI file explorer, you would double-click to open a file folder. In a terminal, you are still doing the same things – opening folders, opening files, adding and removing things – they just look different.

For these exercises, I am going to use PowerShell inside of the Windows Terminal app.

Check Your Current Location

In the GUI, you can just look up at the top bar and see your current folder in the file system.

In PowerShell, use the Get-Location or pwd commands. pwd stands for Print Working Directory – or print the directory you are currently working in.

Get-Location

Path
----
C:\Users\Test\Desktop\Test Folder


pwd

Path
----
C:\Users\Test\Desktop\Test Folder


List the Contents of the Current Directory

Use the Get-ChildItem or ls commands.

Get-ChildItem


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/13/2022   6:11 PM                folder1
d-----         1/13/2022   6:11 PM                folder2
d-----         1/13/2022   6:11 PM                folder3
-a----         1/13/2022   6:18 PM              0 file1.txt
-a----         1/13/2022   6:18 PM              0 file2.txt
-a----         1/13/2022   6:18 PM              0 file3.txt


ls


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/13/2022   6:11 PM                folder1
d-----         1/13/2022   6:11 PM                folder2
d-----         1/13/2022   6:11 PM                folder3
-a----         1/13/2022   6:18 PM              0 file1.txt
-a----         1/13/2022   6:18 PM              0 file2.txt
-a----         1/13/2022   6:18 PM              0 file3.txt


Create a Directory

Use the New-Item or mkdir commands

New-Item -ItemType Directory -Name 'folder4'


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/13/2022   6:30 PM                folder4


mkdir folder5


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/13/2022   6:31 PM                folder5


Rename a Directory

Use the Rename-Item, Move-Item, or mv commands. Seeing the word move when talking about renaming something can be confusing.

# Whenever a name contains a space
# You must wrap it in single or double quotes

Rename-Item folder1 'folder 1'
Move-Item 'folder 1' folder1
mv folder1 folder-1


Delete a Directory

Remove-Item folder4

# Use the -Recurse -Force options
# To delete a folder that is not empty
Remove-Item folder5 -Recurse -Force


Create a File

New-Item -ItemType File -Name 'file4.txt'


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         1/13/2022   6:34 PM              0 file4.txt


Rename a File

Rename-Item file1 .txt 'file 1.txt'
Move-Item 'file 1.txt' file-1.txt
mv file-1.txt file1.txt


Delete a File

Remove-Item 'file4.txt'


Moving in and out of Directories

These are called relative paths:

  • . is another way to say the current folder
  • .. is another way to say the parent folder – or the folder above this one

They are not absolute paths, because they don't reference the entire base of the current directory. There's no explicit reference to the parent(s).

Let's take a look at the contents in the current directory again:

ls


    Directory: C:\Users\Test\Desktop\Test Folder


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         1/13/2022   6:11 PM                folder-1
d-----         1/13/2022   6:11 PM                folder2
d-----         1/13/2022   6:11 PM                folder3
-a----         1/13/2022   6:18 PM              0 file1.txt
-a----         1/13/2022   6:18 PM              0 file2.txt
-a----         1/13/2022   6:18 PM              0 file3.txt
-a----         1/13/2022   6:34 PM              0 file4.txt

We can identify a directory easily, as they start with d-----. I am going to change into the directory folder2

# The .\ syntax is saying
# the current folder and then
# the file or folder within
# this location

cd .\folder2

pwd

Path
----
C:\Users\Test\Desktop\Test Folder\folder2

Now, I am in the folder2 directory and the parent directory is Test Folder. I am going to go up a level and back into the Test Folder directory.

cd ..

pwd

Path
----
C:\Users\Test\Desktop\Test Folder

I am now back in the Test Folder directory.

Finally, I can move to a completely different directory by providing its absolute path.

Set-Location 'C:\Windows\System32'

pwd

Path
----
C:\windows\System32

Refer back to this article for a refresher on some other basic PowerShell commands if needed.

PowerShell as Your First Programming Language
In this post, I discuss why PowerShell makes a great first programming language




Variables

Create the Script File

Go to File > Save and save your file as variables.ps1. I created a new folder to store my script files.  Fill out these fields as shown below and click Save.



What is a Variable?

In programming, a variable is a placeholder where we can put some data that can be referenced repeatedly throughout the lifetime of the script or program.

The placeholder's name never changes, although the contents inside of the placeholder may change and that is why it is called a variable.



Write Some Code

Quick Tip: You can put as many comments as you like in your code. Comments are there for you and other people who read your code. The PowerShell interpreter ignores comments and they do not affect the functionality of your code.

# This is a single-line comment

<#
This is
A multi-line comment
This will
Comment out all these lines
#>

# Creates a variable called "name" and stores the value "John Doe"
$name = 'John Doe'
Write-Host "Hello, $name"

# The variable already exists, change the value stored inside to "Jane Doe"
$name = 'Jane Doe'
Write-Host "Hello, $name"

Press the Run button and observe the output in the integrated PowerShell console window.





Data Types

Create the Script File

Go to File > Save and save your file as data-types.ps1.

Common Data Types

Some primitive data types that you should know for programming are:

  • Integer
  • Floating-point (number with a decimal point)
  • Character
  • String
  • Boolean


Write Some Code

$integer = 10
$float = 10.1
$boolean = $false

# A string may be wrapped in
# Single quotes ' '
# Or, double quotes " "
$string1 = 'hello world!'
$string2 = "100"

# Must specify [char] here
# Because PowerShell will try to cast it as string
[char]$char1 = 'y'
[char]$char2 = '1'

$integer.GetType()
$float.GetType()
$boolean.GetType()
$string1.GetType()
$string2.GetType()
$char1.GetType()
$char2.GetType()


Review the Output

  • 10: Int32 is a 32-bit integer
  • 10.1: Double is a kind of floating point integer
  • $false: Boolean is a True or False value; on or off
  • 'hello world!': String
    • When you hear the word string, just imagine a piece of string and you are adding each letter to the string one at a time.
    • I say this because a string is actually just a connection of individual characters *
  • "100": String
  • y: Char a single character
  • 1: Char a single character


* More Info About Strings

I told you to imagine a piece of string and you are putting the letters of the word on the piece of string one at a time. I said that a String is just a connection of individual characters. Let me demonstrate.

Let's take the word superman for example. The word superman is 8 characters long. So, you've placed 8 letters onto your piece of string.

With computers, counting starts at 0. So, 0 is getting the first character from the string superman, which is the letter s.



More Info About Data Types

PowerShell – like Python – is a flexible language. It is not inherently a strictly type-enforced language. This is because the PowerShell interpreter makes a best effort to classify the data you are entering.

The interpreter is what runs your code when you press the Run button. This is known as a REPL. Read Evaluate Print Loop – the interpreter reads your code, processes it, prints output to the screen, and loops back to restart the process.

With PowerShell, you can manually cast an input as a certain type. Here are some examples:

# PowerShell will interpret this an integer
100

# PowerShell will interpret this as a string
'a' 

# PowerShell will interpret this as a double
3.14


# Cast the integer as a string
[String]100

# Cast the double as a string
[String]3.14

# Cast 'a' as a char, not a string
[Char]'a'

# Cast 'f' as a byte
[Byte]'f'

# True, on
[Bool]1

# False, off
[Bool]0




Arrays

Create the Script File

Go to File > Save and save your file as arrays.ps1



What is an Array?

Think of an array as a shopping cart. You can put all kinds of things in a shopping cart. The shopping cart is holding a collection of items. Some arrays can hold a collection of items that are totally unrelated.

You can make arrays that more strict. Again, imagine a shopping cart, but this shopping cart is only allowed to hold a collection of fruit. Some arrays have this kind of behavior.



Write Some Code

$integer = 10
$float = 10.1
$boolean = $false
$string = 'hello world!'
$char = 'y'

# Put some items in the array
# This array is going to hold
# An integer, a flow, a char, a string, and a boolean type
$array = @($integer, $float, $boolean, $string, $char)

# Return is a keyword that will return
# A value back to the standard output
return $array




Operators

Create the Script File

Go to File > Save and save your file as operators.ps1

PowerShell Operators

Most operators are standard across programming languages, but PowerShell has a few operators that don't align with what you will see in other languages

  • Arithmetic Operators
    • + addition
    • - subtraction
    • * multiplication
    • / division
    • % modulo (divide and return remainder)
  • Relational Operators
    • -eq (usually == or === in other languages)
    • -ne (usually != in other languages)
    • -gt (usually > in other languages)
    • -lt (usually < in other languages)
    • -ge (usually >= in other languages)
    • -le (usually <= in other languages)


Write Some Code

1 -eq 1
2 -eq 1
'a' -eq 'a'
'a' -eq 'b'
'a' -ne 'b'
$true -eq $true
$false -eq $true
2 -ne 1
5 -gt 2
4 -lt 3
2 -lt 5
10 -ge 10
10 -ge 9
9 -ge 10
10 -le 10
10 -le 11
9 -le 10
20 * 2 -gt 10 * 2
2 * 2 -eq 4




Functions

Create the Script File

Go to File > Save and save your file as functions.ps1



The Use of Functions

DRY code is good code. Don't Repeat Yourself. In other words, if you find yourself repeating code multiple times, then it's time for a function.

A function is a piece of code that is designed to do one task really well. Functions should be lean and precise.



Example of Code that is Not DRY

Here is some code where we want to check if two numbers added together are less than 5. This code is not DRY, because I've repeated the same code block twice. This is a very contrived example, but it is true nonetheless.



Example of DRY Code

I used some color-coded lines to demonstrate how the parameters are linked within the function and the user input. $firstNumber and $secondNumbers are variables that will hold user input when the function is called. These variables are referenced internally inside the function.

$firstNumber and $secondNumber are called parameters. Then, when the function is called – as pictured above – and input is provided, that is called passing an argument to a parameter.



Write Some Code

function Confirm-UserIsValid ($firstName, $lastName) {
	
    $allowedUser = 'John.Doe'
    $username = "$firstName.$lastName"
    return $username -eq $allowedUser

}

# Passing the arguments: Jane and Doe
Confirm-UserIsValid -firstName 'Jane' -lastName 'Doe'

# Passing the arguments: James and Doe
Confirm-UserIsValid -firstName 'James' -lastName 'Doe'

# Passing the arguments: John and Doe
Confirm-UserIsValid -firstName 'John' -lastName 'Doe'


Follow Up

Notice how I create a new variable using the existing variables:
$username = "$firstName.$lastName". What I've done is created a String by wrapping the variables in double quotes.

What would happen if I had written it like this: '$firstName.$lastName'? Let's use some code to find out.

Why did that happen? When you wrap a string in single quotes, you create a string literal. That means anything between the single quotes should be interpreted exactly as it appears, so don't interpret the variables to their values.





Control Flow

Create the Script File

Go to File > Save and save your file as control-flow.ps1



Using Logic to Control a Script

The whole point of control flow is to direct the outcome of a script. When you use control flow you are saying, "If something is true, do this." This where the concept of Boolean logic is factored into programming.

Remember that Boolean is true or false. If something is true, do this; otherwise, do this. Or, if something is false, do this; otherwise, do this.



Code Example 1

$age = 20
if ($age -le 10) {
    # Run this code if
    # Age is less than or equal to 10
    Write-Host "Your bedtime is at 8:00 PM"
}
elseif ($age -gt 10 -and $age -le 18) {
    # Otherwise
    # Run this code if
    # Age is between 11 and 18
    Write-Host "Your bedtime is at 10:00 PM"
}
elseif ($age -gt 18 -and $age -le 30) {
    # Otherwise
    # Run this code if
    # Age is between 19 and 30
    Write-Host "Your bedtime is at midnight"
}
else {
    # Otherwise
    # Run this code if
    # Age is any other number
    Write-Host "Your bedtime is at 11:00 PM"
}

These conditions are all chained together.

if (try this first)
elseif (then, try this)
esleif (then, try this)
else (run this if all else fails)


Code Example 2

$string = 'code'
if ($string -eq 'code') {
    Write-Host "Code! Nice!"
}
if ($string.Length -eq '4') {
    Write-Host "Your string is 4 characters long."
}
if ($string -eq 'yoda') {
    Write-Host "Do or do not, there is no try."
}

These conditions are not chained together. Each if clause will run independently regardless of the result of the last if clause.

if (try this)
if (also, try this)
if (also, try this)


Code Example 3

$color = 'orange'
switch ($color) {
    
    'red' {
        Write-Host "Red."
        break
    }
    'orange' {
        Write-Host "Orange."
        break
    }
    'yellow' {
        Write-Host "Yellow."
        break
    }
    'green' {
        Write-Host "Green."
        break
    }
    'blue' {
        Write-Host "Blue."
        break
    }
    'indigo' {
        Write-Host "Indigo."
        break
    }
    'violet' {
        Write-Host "Violet."
        break
    }
    default  {
        Write-Host "Enter a valid color."
        break
    }

}

The break keyword tells the program to stop testing conditions once a match has been found. The default keyword tells the program to run this code if nothing matches.





Loops

Create the Script File

Go to File > Save and save your file as loops.ps1



What are Loops?

Loops are useful for:

  • Running a block of code a specific number of times
  • Processing arrays


Beware of Infinite Loops

Infinite loops are loops where you have created a condition that will unceasingly be True. Infinite loops will break a program and can crash a computer.



Example of an Infinite Loop

while ($true) {
	Write-Host "Infinite loop!"
}

Why does this cause an infinite loop? Because, $true never stops being $true. The output just keeps going and going. If you ever get into an infinite loop, you can stop it by pressing CTRL + C, which should discontinue script execution.



Types of Loops

  • for
  • foreach
  • while
  • do while


Code Example 1

$repetitions = 10
for ($counter = 0 ; $counter -lt $repetitions ; $counter++) {
    Write-Host "Loop $counter"
}

I want my code to loop 10 times. Remember that in computing, counting starts from 0. Let's take a look at what this loop does.

  • $repetitions = 10: The number times I want the code to repeat
  • $counter = 0: I am going to start my loop counter at zero
  • $counter -lt $repetitions: Run the loop as long as this is true
  • $counter++: $counter started at 0, ++ means add 1 to that value, so now $counter is equal to 1. It will continue to increment by one at each loop.


Code Example 2

# Make an array of animals
# It's an array of strings
# Each string is an animal name
$animals = @('dog', 'cat', 'parrot', 'horse')

foreach ($animal in $animals) {
    Write-Host "Say hello to the $animal"
}

Let's take a look further at how this loop works.

Pretend you have a bucket of $animals. You are going to take one animal out at a time and place it in $animal. You keep repeating this until you've emptied the $animalsbucket.



Code Example 3

$counter = 0
while ($counter -ne 10) {
    Write-Host $counter
    $counter++
}

In the case of the while loop, the program keeps processing the code while the condition is true.



Code Example 4

$counter = 0
do {
    Write-Host $counter
    $counter++
}
while ($counter -ne 10)

Similar to the while loop, the do while loop is simply saying do this while this condition is true.





Final Project

function Get-RandomNumberFromRange ($startingNumber, $endingNumber) {
	
    # With integers you can create an array of integers easily
    # For example 1..10
    # Will create an array from 1 to 10
    # In this case we'll create an array of integers
    # Between the start and end numbers
    
    $numberArray = $startingNumer..$endingNumber
    
    # This is called passing input down the pipeline
    # We pass the $numbers variable to the
    # Get-Random cmdlet
    # The Get-Random cmdlet will pick a random number
    # From the array of numbers
    
    $randomNumber = $numberArray | Get-Random
    return $randomNumber
}

# Integers
# If you wrapped them in quotes
# They'd be strings 
# And, it would break the program
$start = 1
$end = 20

$randomNumber = Get-RandomNumberFromRange -startingNumber $start -endingNumber $end

Write-Host "Let's play a guessing game" -ForegroundColor Green
Write-Host "I will choose a random number between $start and $end" -ForegroundColor Magenta
Write-Host "See if you can guess what it is" -ForegroundColor Cyan

# The Read-Host cmdlet is how you get input from a user
$guess = Read-Host -Prompt "Enter a number between $start and $end"

while ($guess -lt $start -and $guess -gt $end) {
	$guess = Read-Host "Your choice was not between $start and $end, try again"
}

if ($guess -eq $randomNumber) {
	Write-Host "Great guess! The random number is: $randomNumber and you chose: $guess!" -ForegroundColor Green
}
else {
	Write-Host "Better luck next time. The number is: $randomNumber and you chose: $guess." -ForegroundColor Yellow
}




Intro to Object-Oriented Programming

When you're comfortable with the concepts here, head on to the next post for a brief introduction to object-oriented programming with PowerShell.

Intro to Object-Oriented Programming with PowerShell
In this post, I go over the fundamentals of object-oriented programming and some simple ways to use them in PowerShell

Spread the word

Keep reading