Where-Object Vs .Where()

As of powershell 4 there is an alternative way of filtering collections using Where() method. This has some more advanced options that can be quite useful. This method will only be available on collections.

#Comparison of the two types

Get-Service | Where-Object {$_.Status -eq 'Running'}

(Get-Service).Where({$_.Status -eq 'Running'})

The Where() method has some extra arguments it can take that make it able to do more dynamic filtering. You call the method as below:

Where({ expression } [, mode [, numberToReturn]])

The modes available are:

  • Default – Returns all objects that resolved $true
  • First – Returns only the first object that resolved $true
  • Last – Returns only the last object that resolved $true
  • Until – Will return all objects until the first that resolve $true
  • SkipUntil – Will not return any objects until one resolve $true
  • Split – Out puts filtered groups one after the other

Which allow us to do things such as:

#Filter a group and split results into separate variables for later use
PS C:\> $Up,$Down = (Get-NetAdapter).Where({$_.Status -eq 'Up'}, 'Split')

#Filter and return all objects that have a status of okay until you hit the first error.
#This might be helpful for tracing up to what point something has succeeded.
PS C:\> ('ok','ok','ok','error','ok').Where({$_ -eq 'error'}, 'Until')

#The reverse of until could potentiall be used to show you events took place after an error had occurred.
PS C:\> ('ok','ok','ok','error','ok').Where({$_ -eq 'error'}, 'SkipUntil')

It is worth noting also what the Where() method is significantly faster than the traditional Where-Object

#Find all numbers that are divisible by 3 in 1 to 1000000
Measure-Command { 1..1000000 | Where-Object {$_ % 3 -eq 0}} | Select TotalSeconds

Measure-Command {(1..1000000).Where({$_ % 3 -eq 0})} | Select TotalSeconds


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.



Changes to Windows 10 Updates

A lot has changed coming from Windows 7 to Windows 10. One such thing is the way in which Windows Updates now works. This has been a bit of a hiccup for me in getting the OS deployable so here are some of my notes on what I have learned so far:

Windows Update Log

Historically WindowsUpdate.log has been located in pain text in C:\Windows\. Now however all windows update logs go through event log tracing. to get a human readable format of this you will need to do the following

#Nice and simple

#Specify a symbol server to use
Get-WindowsUpdateLog -Symbol Server "\\someserver\symbol"

Note here that this function will use and cache symbols from the internet to decode the etl logs. If you dont have access to the internet such as on a domain then you can specify a symbol server. In theory you wouldn’t need to do this if you setup _NT_SYMBOL_PATH correctly but i have yet to get that working.

Upon running the above the symbol cache and etl files are all now stored in $env:TEMP\WindowsUpdateLog. If for some reason you need to clear the logs (for a fresh view of whats happening) you can do so by running:

#Flush all windows update logs
Get-WindowsupdateLog -ForceFlush


Delivery Optimization

Windows update now downloads updates in a different way. A great article that explains the differences in detail is below:

Windows 10, Delivery Optimization, and WSUS: Take #2

To simplify things I am only interested in behaviors in version 1607. To my understanding the download modes I want to pick from are:

  • Simple – No peering. Delivery Optimazation will not contact the internet and instead use HTTP to the configure WUServer (WSUS or internet) This is a good setting for enterprise to limit intenret traffice (In my case its blocked by a proxy anyway)
  • Bypass – Do not use Delivery Optimization and use BITS instead

You can configure these and other settings in Group Policy  Computer Configuration > Administrative Templates > Windows Components > Delivery Optimization. Settings applied via group policy will appear here in the registry.



Using Internal WSUS Server

This is proving a problem. In lieu oh actually getting this working here is an article I will be working through

Manage Windows 10 Update Using WSUS


Automation using PSWindowsUpdate

Luckily (for now at least) Windows Update looks to still use the same old com objects as it always has done. I have a few scripts that utilize these so this helps. However moving forward however I am trying to use a newly found module form PSGallery that works nicely so far with packer.

For instance to install Windows updates using powershell:

#Install the module form PSGallery
Install-Package -Name PSWindowsUpdate

#Import and Install any available updates
Import-Module PSWindowsUpdate
Get-WUInstall -AcceptAll -IgnoreReboot -Verbose


The below is an example of running Powershell tasks Asynchronously using a Runspace Pool. Runspaces are a bit more complex but a lot faster than Powershell jobs. I have saved this framework as a snippet so that I can insert and edit very easily.

This and more examples can be found on my Github

First you want to setup your runspace pool. A useful thing to remember here is that you can create a custom session state that has all the required modules imported to save on importing for each task!

#Create an Array List to Track Jobs
$Runspaces = [System.Collections.ArrayList]::new()

#Create the Runspace Pool
$SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$RunspacePool = [runspacefactory]::CreateRunspacePool(
   1, #Min Runspaces
   10, #Max Runspaces
   $SessionState, #Initial Session State
   $host #System.Management.Automation.Host.PSHost

Now you can populate the runspace with tasks. here i just add 20 instances of a script that will wait a random amount of time and inform you when it started and ended

1..20 | ForEach-Object {
   #Define the Script and Params
   $Params = @{
      Seconds = Get-Random -Minimum 1 -Maximum 11
   $Script = {
      $ThreadID = [System.AppDomain]::GetCurrentThreadId()
      Write-Output "Starting ThreadId $ThreadID"
      Start-Sleep -Seconds $Seconds
      Write-Output "Ending ThreadId $ThreadID after $Seconds seconds"

   #Create Powershell Instance for your job
   $PowerShell = [System.Management.Automation.PowerShell]::Create()
   $PowerShell.RunspacePool = $RunspacePool

   #Invoke Async and Track
      Runspace = $PowerShell.BeginInvoke()
      PowerShell = $PowerShell

You will want to track the progress and output of the tasks. To do so you can query the runspace foir completed jobs. Any completed jobs you can EndInvoke() and Dispose() to get the output and cleanup as you go

#Retreive output and cleanup as jobs complete
Do {
   $More = $false
   $CompletedRunspaces = [System.Collections.ArrayList]::new()
   $Runspaces | Where-Object -FilterScript {$_.Runspace.isCompleted} | ForEach-Object {
   $CompletedRunspaces | ForEach-Object {
   If ($Runspaces.Count -gt 0) {
      $More = $True
      Start-Sleep -Milliseconds 100
While ($More)

Advanced Sort-Object

Sort-Object can be used in a few ways which allow a very powerful methods for sorting objects in weird and wonderful ways. Here is a simple example:

$Data = Get-Service

#First Alphabetically by Status, Then by Name
$Data | Sort-Object -Property Status,Name


The Property parameter accepts an String or an Object. If we use a Hashtable as input here Sort-Object will look for Expression (A Script Block) and Ascending and Descending (Both Boolean) which can be used to make customize sorting logic. Here some more complex:


#First Where Name Matches ^win, Next by Name Matches ^SQL, The rest Alphabeticaly by name
$Data | Sort-Object -Property @{Expression = {$_.Name -match '^Win'}; Descending = $true}, @{Expression = {$_.Name -match '^SQL'}; Descending = $true},Name

Status Name DisplayName 
------ ---- ----------- 
Running WinDefend Windows Defender Service 
Running WinHttpAutoProx... WinHTTP Web Proxy Auto-Discovery Se...
Running Winmgmt Windows Management Instrumentation 
Running WinRM Windows Remote Management (WS-Manag...
Stopped SQLAgent$SQLEXP... SQL Server Agent (SQLEXPRESS) 
Running SQLBrowser SQL Server Browser 
Running SQLWriter SQL Server VSS Writer 
Stopped AJRouter AllJoyn Router Service 
Stopped ALG Application Layer Gateway Service 
Stopped Apache2.4 Apache2.4 
Running AppHostSvc Application Host Helper Service 


#Conditional Logic to Update an object as part of the sort.
$Data | Sort-Object -Property @{Expression = {If($_.Name -match '^Win'){$_.Name = 'HIDDEN'}}; Descending = $true}

Stopped WerSvc Windows Error Reporting Service 
Stopped WiaRpc Still Image Acquisition Events 
Running WlanSvc WLAN AutoConfig 
Stopped wlidsvc Microsoft Account Sign-in Assistant 
Stopped WebClient WebClient 

Using Powershell to Change Network Settings

When administering Server 2012 without the GUI these come in very handy to know:

#Set an IPAddress
New-NetIPAddress -InterfaceAlias 'vEthernet' -IPAddress '' -PrefixLength 24 -Verbose

#Set DNS Information
Set-DnsClientServerAddress -InterfaceAlias 'vEthernet' -ServerAddresses

#Change Network Profile
Get-NetConnectionProfile -Name 'Unidentified network' | Set-NetConnectionProfile -NetworkCategory Private -Verbose