Code Snippets


The TechSnips site is a great resource for learning and especially PowerShell, so check out TechSnips/SnipScripts: This is where all scripts demonstrated by our TechSnips contributors will be provided free of charge for lots of small pieces of code.


There are two ways to add comments to a PowerShell script.

Line Comment

Just make sure the line starts with a hash character or # and the whole line will be ignored and treated as a commend. I sometimes put these on a line after my code, to explain what it does, so you can just comment out the last part of a line, if you want.

Block Comment

You can comment out a whole block of code be enclosing it within "<#" and "#>", however this also has a special purpose for documenting your code, see about_Comment_Based_Help for details.

Hide Output

Some commands default to giving output to the console, New-Item for example does this. However it is not hard to suppress this as in the following example:
New-Item -ItemType Directory "C:\Temp\NewFolder" | Out-Null

Read File

There seems to be one standard, reliable approach, which is as follows: $content = [IO.File]::ReadAllText(".\test.txt"), this works well, however in PowerShell 3 and above you can use $text = Get-Content .\file.txt -Raw . Note that without the -Raw you will get an array of lines.

Environment Variables

I suggest you just read Windows PowerShell Tip: Creating and Modifying Environment Variables not much value I can add to that! However, if you want to get the value of the logonserver environment variable you can do this with $Env:logonserver, which is nice and easy. You might also want to read Windows PowerShell Cookbook - View and Modify Environment Variables.


There are a number of options when looping: For, ForEach, While, Do...While, Do...Until, these are all described at PowerShell Loops - TechNet Articles - United States (English) - TechNet Wiki. However, if you want to exit a loop "early" then use Break.

Some examples:
$array = 1,2,3,4,5
ForEach ($value in $array) {
    Write-Host "Value: $($value)"
For ($i; $i-lt5; $i++) {
    Write-Host $i

I have also used ForEach with collections.

Switch and If

You will probably need to read about_Comparison_Operators and about_Logical_Operators if you are using if statements.

Great to see switch working on strings! For examples of using If, see Hey, Scripting Guy! How Can I Use the If Statement in Windows PowerShell? - Hey, Scripting Guy! Blog - Site Home - TechNet Blogs. However the most comprehensive explanation of switch I have seen is Powershell: Everything you ever wanted to know about the switch statement.


The key point to note is that $TRUE and $FALSE represent True and False but see Boolean Values and Operators - Windows PowerShell Blog - Site Home - MSDN Blogs and Understanding Booleans in PowerShell - TechNet Articles - TechNet Wiki for more details. However for comparisons etc see about_Comparison_Operators and also see about_Logical_Operators.

Temporary File

Here is a nice little example of working with a temporary file:
$TmpFile = [System.IO.Path]::GetTempFileName()
Get-ChildItem $TmpFile # Same as ls
Remove-Item $TmpFile
ls $TmpFile

Script Directory

Sometimes you need to know the directory your script file is located in, especially if it is not the current directory. This is easily done with $MyInvocation.MyCommand.Path, well that gets the filename as well, doing Split-Path $MyInvocation.MyCommand.Path will get you just the directory. In PowerShell 2 and above you can use $PSScriptRoot, however it only works in script modules (.psm1) but in PowerShell 3 it works in regular scripts as well.

Launch Child Process

This is quite easily done with Start-Process, however you do have to learn the different paramters that go with this, for example -Wait, -NoNewWindow -RedirectStandardOutput -RedirectStandardError -ArgumentList -PassThru.

It is -PassThru, I want to give an example of:
$Result = Start-Process "CScript" -PassThru -Wait -NoNewWindow -RedirectStandardOutput $OUTPUT_FILE -RedirectStandardError $OUTPUT_ERR_FILE -ArgumentList ".\VBScript.vbs arg1 arg2"
if ($Result) # This actually means "if not null"
  Write-Host $Result.GetType().FullName
  Write-Host $Result.ExitCode

Defining Variables

You can define a variable in two different ways, as follows:
$var1 = 100
Set-Variable var2 200

In both these cases the values are changeable. You can make a variable read-only like this:
Set-Variable -Option ReadOnly var3 300
Then if you try to change the value you get an exception. However you can delete the variable and re-create it, although removing requires the use of the "force" option as seen in the folloing example:
Remove-Variable -Force var3
If you want to create a real constant that cannot be changed or remove, even with a force, then you need this:
Set-Variable -Option Constant var4 400
Set-Variable -Option Constant -Name var4 -Value 400

Type Information

To display full type information of a variable use one of the following:
Where the first gives you all the type iformation and the second the complete type name, which is useful for testing for a type, which is done as follows:
if ($var -is [System.DateTime]) ...


This is one of those sometimes useful programming constructs and other times troublesome. If you want a null, then in PowerShell you can use $null. It is well worth reading Powershell: Everything you wanted to know about $null to fully understand how null works in PowerShell.

PowerShell Versions

Example code for getting the versions:
Write-Host "PowerShell Version: $($PSVersionTable.PSVersion)"
Write-Host "Compatible Versions: $($PSVersionTable.PSCompatibleVersions)"
ForEach ($version in $PSVersionTable.PSCompatibleVersions) {
    Write-Host "-Version: $version"


There are plenty of interesting options documented at Environment Class (System), however the following code has proved useful:
Write-Host "Is this 64-bit PowerShell? $([Environment]::Is64BitProcess)"
It is worth reading the link and seeing what else you can do.

Platform Differences

One commonly encountered difference between Windows and Linux is the "new line" characters. So if you want to get and use the new line characters for the current platform then I suggest a definition as follows:
Set-Variable -Option Constant -Name "newline" -Value $([Environment]::NewLine)
This constant is then easy to use but it is defined at runtime.

Adding Users to Groups

This is a handy but simple code example that adds a domain user account to a group on the local machine. This is handy when the visual Computer Management tools are not available or you are running Server Core. To add the user account "john.smith" from the "CORP" domain into the local computer's Power Users group execute the following line of PowerShell:
([ADSI]"WinNT://$env:computername/Power Users,group").Invoke('Add', "WinNT://CORP/john.smith")
You can clearly wrap this into a function and get user input at runtime etc but this is the basic.

By way of reference the above is the same as the following:
net localgroup "Power Users" /ADD CORP\john.smith

Sending E-Mail

The key is using Send-MailMessage, however I would recommend also using Get-Credential to control the message displayed to the user.

String Splitting

One approach is to find the position of the separator and then get the text before and after it, as follows:

$text = "One,Two,Three;Four;Five-Six"
$pos = $text.IndexOf(";")
$leftPart = $text.SubString(0, $pos)
$rightPart = $text.SubString($pos+1)
This results in $leftPart having the text "One,Two,Three" and $rightPart having the text "Four;Five-Six". This technique is nice and simple and clear, however it really only works with one separator and two parts.

The second approach, which gives the same output is $text.Split(";", 2), however this returns an array, so the left part is $text.Split(";", 2)[0] and the right part is $text.Split(";", 2)[1], note that the number 2 specifies a maximum of two parts. If you leave the number off then every semi-colon is treated as a separator. Furthermore if you use $text.Split(",;-") then all three of those characters are used as separators and 6 items are returned, each one containing a word.

Counting Lines

You can use the Measure-Object cmdlet for this, as follows:
dir -Recurse *.txt | Get-Content | Measure-Object -Line
However, I have noticed it does not count blank lines or lines that are just whitespace.

Windows 10 Apps

This is a nice neat one-liner to get all the "apps" installed on Windows 10:

Get-AppXPackage | Select-Object -Property Name, Publisher | Sort-Object -Property Name


Although PowerShell Performance: Filtering Collections is focused on performance it is a useful summary of ways to filter.

Windows Firewall

Originally I was looking for a way to create a group in the "Windows Firewall with Advanced Security" on a Windows Server 2016 box. I do not believe this can be done through the user interface, and so it is easier to use PowerShell to create new rules, see New-NetFirewallRule for the documentation and below for my example:

New-NetFirewallRule -DisplayName "GDS Server" -Group "GeoffDoesStuff" -Description "Allow remote access to the specified ports" -Profile Public -Direction Inbound -Action Allow -LocalPort 9400-9409 -Protocol TCP

Admin Rights Check

$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal] $identity
if ($principal.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Host "Running with Administrator privilege"
} else  {
    Write-Host "Running as standard user"