Powershell Basics: Writing Classes

As of PowerShell 5.0 you can create your own classes. A class is a template or definition of an object. Conversely an object is an instance of a class. Classes can contain methods, properties, enums, and other things.

#Define the Class
Class RandomBattle {
   #Define Properties of this class
   #Using the static keyword makes this property always available
   static [Int]$PartyMemberCount = 3

#Instantiate a New Object
$Battle = New-Object RandomBattle
$Battle.EnemyCount = 5

#Access the static Property we assigned


Adding Enums

Using Enums is a good way of validating the data going in by restricting it to an enumerated set of values.

Class RandomBattle {
   static [Int]$PartyMemberCount = 3
   #Add the defined Enum as a property in your class

#Define the Enum
Enum PartyMembers {
   Cloud = 1
   Tifa = 2
   Barret = 3

#Here is the Enum working on its own
#Here we Instantiate a New Object and set the NextTurn Property which is an Enum
$Battle = [RandomBattle]::New()
$Battle.NextTurn = 1


Adding Methods

You can also add methods to your class. Note here that we refer to the object that called the method as $this in the method definition. You can write methods without parameters by simply using ()

Class RandomBattle {
   static [Int]$PartyMemberCount = 3
   EnemyKO($count) {$this.EnemyCount -= $count }

$Battle = [RandomBattle]::New()
$Battle.EnemyCount = 5


Throwing Errors

Instead of Write-Error or PSCmdlet.ThrowTerminatingError, in Classes you should use the Throw Key word.

Class RandomBattle {
   EnemyKO() {
      Try {
         #Some failing command
      Catch {
         Throw $_
         Throw "Custom Error Message"

Inheriting Classes

It is important to design your classes well. For that reason class inheritance is often important. If you can identify properties,methods, etc that are common to different classes you will be working with you can inherit these from a parent class

#Define Class with Common Properties
Class Battle{
   static [Int]$PartyMemberCount = 3
#Define Class with more specific properties. The ':' means inherit
Class RandomBattle : Battle {
Class BossBattle : Battle {
   PlayCinematic() {
      Write-Host "Aeries no!"

$Rand = [RandomBattle]::new()
$boss = [BossBattle]::new()


The Using Statement

This new Powershell 5.0 Keyword allows you to import other powershell classes from modules and to also import namespaces allowing you to reference .NET classes by there name only

Using Namespace System.Xml.Linq
Using Module MyClass

#Instead of the long [System.Xml.Linq.XDocument]::new() we can just use:
$XDoc = [XDocument]::new()

#Becuase we are Using the MyClass class we can instantiate MyClass:

Powershell Basics: Writing Modules

There is no “one” design pattern when it comes to writing modules. The choices you make when building one largely depend on the size, complexity and use case. Rather than describe “How to build a module”, I have instead created a template module where I can throw in different ideas and test new styles. This can be found here and is well commented:


This serves as a starting point for me. Below are some of the features I have used. These are all optional allowing me to pick and choose what I want or need depending on the modules:


Using InvokeBuild to Compile From Source

Simply, the idea is to write all your code in a neat maintainable way but then compile the source into a performant, only-what-you-need powershell module. I do this by keeping functions and classes in separate files contain in each folder:

  • .\PSModuleTemplate\Classes – Contain each PS Class
  • .\PSModuleTemplate\Public – Contain functions that will not be exported
  • .\PSModuleTemplate\Private – Contain functions that will be exported
  • .\PSModuleTemplate\PSModuleTemplate.psd1 – The module manifest
  • .\PSModuleTemplate\PSModuleTemplate.psm1 – Temporary module loader

The module loader pulls together classes, private and public functions by dot sourcing (or using the using statement for classes). However this is only used to facilitate development. dot sourcing is expensive and can cause massive delays when loading modules with lots of functions.

Instead when I am happy with the source files I call Invoke-Build. This will action the steps found in .\PSModuleTemplate.build.ps1. This will compile each constituent script into a single psm1 file and update the module manifest accordingly straight into the PSModulePath. It is this compiled version of the module that you will want to deploy.


CI Engine (Bamboo, AppVeyor)

InvokeBuild works well locally to develop and test a module. But its true purpose is to facilitate Continous Integration. There are a few such CI Engines, I have only included AppVeyor and Bamboo out of preferences but in theory the PSModuleTemplate.build.ps1 can be used with any other CI.

I have configured GitHub with a commit web hook that will trigger AppVeyor for example to start a new build.

AppVeyor will now spin up a new virtual environment for me as configured in appveyor.yml. Here the same steps will be followed as when I compile, analyze and test the module locally with the addition of AppVeyor tracking and updating the build number in the ModuleManifest. Logically if the build suceeds you would want extra steps for deploying the module into production (or into PSGallery for the community) . At time of writing I have not had a chance to play with this.


Pester Tests 

…are a must. These are also called by InvokeBuild after the module is compiled to check for errors. Pester is a big topic that I intend to make a separate blog post on.



This is also called from Invoke-Build in order to check the standards of code are as high as expected. This is especially important when multiple people are working on the module. The level to which PSScriptAnalyzer checks your code is defined in .\ScriptAnalyzerSettings.ps1. Here you can specify what checks to enable/disable which will again depend on the project


Generate Markdown Docs

I find text based help written into each function itself is both help for to me and the end user (obviously) which is why i prefer this method. To get all that text based help out of the source code and into a pretty format for people to view is done by using PlatyPS. This is again called via Invoke-Build but is a separate standalone task that I will do before committing new work. At time of writing I have yet to decide on a way to automate this better but its serves the purpose of producing up to date documentation on demmand.


Format Files 

Format files are great for creating user friendly views. Create a file in the module folder called <ModuleName>.format.ps1xml. For info on all the controls you can use see: Writing a Windows Powershell Format File.

Instead of reloading the module you can force an update of any changes to this file by using

Update-formatdata –prependpath PathToFormattingFile

Below are a few examples of a simple formats.

Simple Table:

<?xml version="1.0" encoding="utf-8" ?>


Simple List:

<?xml version="1.0" encoding="utf-8" ?>


PowerShell Basics: Writing Functions

Defining a Function
This is the basic template that should be used for any functions.

function Verb-Noun {


Process Order
The BEGIN and END blocks only run once. The PROCESS block will act differently depending on how you call the function.

#Will execute the PROCESS block only once for $Input.
#Therefore if $Input is an array you will need a foreach loop to handle each object.
Verb-Noun -Input $Input

#Will execute the PROCESS block once for each element of $Input as it is piped into the function one by one.
$Input | Verb-Noun


Cmdlet Binding
Using the [CmdletBinding()] tag allows the use of -Verbose but you can also set more advanced features such as the SupportsShouldProcess

function Verb-Noun{


Defining Parameters
The following are the different options you can set when defining a paramter. Note that Options of the same type can be added to the same line within the brackets separated by a “,”

function verb-noun{
      [parameter(ParameterSetName = '')]
      [ValidateScript({Script Block to $True/$False})]
      [String / Int / Array]$ParamName


Parameter Set Name
You can define differences in your accepted parameters and give them set name. Powershell will then allow the paramameters to be entered in different ways, eg. pipeline vs. long params. This forces the parameters to be fed into your function how you wish.

function Verb-Noun {
   [CmdletBinding(DefaultParameterSetName = 'Going')]



      Write-Host "Go"
      Write-Host "Stop"
      Write-Host "?"

   Write-Host "$($PSCmdlet.ParameterSetName)"


Dynamic Paramters

Dynamic parameters can greatly help end users in using your custom functions. Below is a quick example of the syntax used, for a worked example on how to implement dynamic parameters see my Github

Function Verb-Noun {
   Param ()
   DynamicParam {
      #Define all Dynamic Parameters in this block
      $DynamicParams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
      Return $DynamicParams


There are a few ways of writing output. The most common is for when writing a function that returns multiple objects as output.

New-Object -TypeName PSObject -Property @{
   'Label 1' = $param
   'Label 2' = $Param.property
   'Label 3' = Some Calculation
} | Add-Member -TypeName 'Something.Something' -PassThru

#Or you can use the Type Accelerator

   StartType = $SvcStartType
   Something = 2048/1GB
} | Add-Member -TypeName 'Something.Something' -PassThru


Output Streams
You can also write to the console using different streams. This is good to avoid writing multiple types of output from a function as this is best practise. In many cases using Write-Host is wrong unless you want to create a user experience.

Write-Verbose "Use this to write more information"

#If you wanted to redirect the verbose (Stream 4) output to a file user:
Test-Script -Verbose 4>&1  | Out-File o.txt

Write-Warning "Error Messages that Stand Out"

Write-Host "Use this to write in different colours" -foregroundcolor "Red"


Help Text
Whilst tedious it is important any tools you make with the intention or reusing them should have ample help text to accompany

<# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER ComputerName Description of parameter .EXAMPLE Example of how to use this cmdlet .EXAMPLE Another example of how to use this cmdlet #>
function Verb-Noun {
   # Some function


Support Should Process

Below is an example of using support for ShouldProcess. The default impact level for the shell to ask the user to confirm is “High” so by setting this as the ConfirmImpact level we are telling the cmdlet to confirm each time ShouldProcess is called. You need to provide a string as an argument. This will be the description of what is about to be done. Using the -WhatIf switch on this function would trigger all ShouldProcess calls but not run them.

function Verb-Noun{
   Param ()

   Write-Host "Performing some basic task"

   If ($PSCmdlet.ShouldProcess('About to make a system change')){
      Write-Host "Performing some high impact task"

Capturing Input with RPi.GPIO

Now that we have experimented with LEDs I want to start capturing basic inputs from buttons using RPi.GPIO. The first question that came up is why do buttons have four pins when they only need two. The answer turns out to be to make them more versatile in making arrays. Articles I found on this went into detail a bit more than I wanted so i made a simple circuit to just test my buttons work the way i expect.



This worked nicely. Pressing the button lights up my LED.

To capture input using RPi.GPIO you will need to set your chosen pins up correctly. It is normal to use what is called a pull-up or pull-down resistor to set the default state of the input pin.

GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

Luckily the raspberry pi allows us to do this in software so my circuit is fairly simple



Wait For Edge

An edge is a change event such as the rising or falling of current over a pin. If you know what input you are waiting for you can pause execution of your program to wait for it by using:


GPIO.wait_for_edge(pin, edge, timeout=5000)




You can poll a pin at anytime using:


However doing this you may miss an input if your program is doing something else at the point in time the button is pressed. Below is a script that polls the state of pin 7 every half a second and prints if the button is pressed or not. Because I am polling, if i press the button too quickly the input is not picked up which is not ideal.



Interrupts – Event Detected & Event Callback

You can add listeners for events on pins to avoid missing inputs as you can with polling:

# setup an event listener

GPIO.add_event_detect(pin, GPIO.FALLING)

# check to see if any events have been recorded


The good news about using this is that your program can continue to do other things and then when its ready check for events it may have missed. The downside is that multiple events are not captured so again you may miss the fact a button was pressed three times. This is where event callbacks come in handy:

# add an event listener AND an event callback

GPIO.add_event_detect(pin, GPIO.FALLING, bouncetime=200)

GPIO.add_event_callback(pin, somefunction)

Using callbacks means that your program can run and at anytime an input is detected the callback function, in this cace somefunction(), will be triggered. This runs in a separate thread so as not to block the main program.

Note also the parameter “bouncetime”. This is to solve in software the electrical problem of “Switch Bouncing”. This can also be done with a resistor

Here are two examples:




Controlling LEDs with RPi.GPIO

The purpose of this exercise is to become familiar with using RPi.GPIO python module to control LEDs using the Raspbery Pi GPIO. For this I have installed Raspbian and run the following to setup the environment.

$ sudo apt-get update
$ sudo apt-get install python3
$ sudo apt-get install python3-pip
$ sudo apt-get install git
$ sudo pip3 install RPi.GPIO
$ git clone https://github.com/mrhockeymonkey/DotPunch.git

I am using a male to male connector to expose the GPIO pins without removing my RPi from the case. this presents a bit of confusion as means the connection for pin 1 now appears on the right hand side if looking at the cable connection head on.

Static LED

First of all I want to create a basic circuit that lights up a single LED. To do this I connect the 3v (P1) and GRND (P6) to my breadboard’s live and neutral bus respectively. I then connect an LED with built in resistor to the live and neutral bus accordingly and the LED is now on.


Blinking LED

Now with the same setup I can start controlling the LED using RPi.GPIO. The script for this is pretty simple. Key points to note for this script are that you must tell the module how you will refer to the pins by using GPIO.setmode() and you must also setup each pin you wish to use as either input or output using GPIO.setup()

import RPi.GPIO as GPIO
import time

# function to blink led with interval 1 second
def blink(pin):
   GPIO.output(pin, True)
   GPIO.output(pin, False)

# use the board pin numbering to refer to pins

# declare pin 7 to be used for output
GPIO.setup(7, GPIO.OUT)

# blink the led 10 times
for i in range(0,10):


Controlling Multiple LEDs

For a bit of fun I have also made a more complex circuit consisting of three LEDs. Each has its own connection to a GPIO pin (Red = Pin7, Yellow=Pin13, Green=Pin15) and then each terminates to GRND.


To control these I wrote a python script to prompt for user input and illuminate the colour LED they specify.