PowerShell Code Snippets

Below are some useful PowerShell code snippets for use in everyday projects.

Sometimes it may be necessary to accept input from the user so that it can be utilised within a script. This can be achieved using the 'Read-Host' cmdlet. Here, the input is placed into a variable called 'user' and then displayed as part of a greeting.

# Greeting variable.
$greeting = "Hello"

# Accept user input.
$user = Read-Host "Please enter your name: "

# Display greeting.
Write-Host "$greeting $user!"

When dealing with directories and files it may be necessary to check for their existence. Below is an example of how to do this.

# Example path and file.
$exampletPath = "C:\demo\";
$exampleFile = "example.txt";

# Check if the path exists.
if (Test-Path($exampletPath))
{

    Write-Host("The path '$exampletPath' exists.")

}
else
{

    Write-Host("The path '$exampletPath' doesn't exist.")

}

# Check if the file exists.
if (Test-Path($examplePath + $exampleFile))
{

    Write-Host("The file '$exampletPath$exampleFile' exists.")

}
else
{

    Write-Host("The file '$exampletPath$exampleFile' doesn't exist.")

}

PowerShell can be used to copy and move files.

# Example paths and files.
$exampletPathSource = "C:\demo\";
$exampletPathDestination = "C:\demo\backup\";
$exampleFile1 = "example1.txt";
$exampleFile2 = "example2.txt";

# Copy the example1.txt file.
Copy-Item ($exampletPathSource + $exampleFile1) `
    -Destination ($exampletPathDestination + $exampleFile1) -Force

# Move the example2.txt file.
Move-Item ($exampletPathSource + $exampleFile2) `
    -Destination ($exampletPathDestination + $exampleFile2) -Force

It is possible with PowerShell to create directories and files, as well as remove them.

# Create a new directory.
New-Item -ItemType Directory -Path c:\output

# Create a new file.
New-Item -ItemType File -Path c:\output\example.txt

# Remove a directory and everything in it.
Remove-Item -Recurse c:\output

Here is an example of how to generate a random number between two values, in this case 1 and 59, then display it.

# Minimum and maximum values for random number.
$minVal = 1
$maxVal = 59

# Generate random number.
$random = Get-Random -Minimum $minVal -Maximum $maxVal

# Display the resulting random number.
Write-Host $random

Here, a random password is generated from a specified set of characters. The length of the password is also randomly selected from a given minimum and maximum length.

# Possible characters in password.
$alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
$numbers = '0123456789'
$nonAlpha = '{]+-[*=@:)}$^%;(_!&#?>/|.'

# Put possible password characters into a character array.
$charSet = ($alpha + $number + $nonAlpha).ToCharArray()

# Minimum and maximum password length.
$minLength = 20
$maxLength = 30

# Select a random password length between the minimum and maximum.
$length = Get-Random -Minimum $minLength -Maximum $maxLength

# Character array for password of the desired length.
$result = New-Object char[]($length)

# Construct new password.
for ($i = 0 ; $i -lt $length ; $i++) {

    # Select a random character from the possible characters array.
    $selected = Get-Random -Minimum 0 -Maximum ($charSet.Length-1)

    # Add the chosen character to the new password.
    $result[$i] = $charSet[$selected]
}

# Display the password.
Write-Host (-join $result)

In order to obtain information about the computer that PowerShell is running on, the 'Get-ComputerInfo' cmdlet can be used.

Get-ComputerInfo

On its own, this cmdlet produces one long list of information relating to the computer concerned. It is possible to limit the details returned by specifying the desired properties, in this case the name and build number of the operating system, as well as the keyboard layout and time zone.

Get-ComputerInfo -Property OsName, OsBuildNumber, KeyboardLayout, TimeZone

If system processes need to be dealt with via the command line, PowerShell provides a number of cmdlets to achieve this. Firstly, the 'Get-Process' cmdlet, used on its own will list all the currently running processes.

Get-Process

This list can be filtered using the 'Id' or 'Name' options. It should be noted that the '*' wildcard can be used if only a partial 'Id' or 'Name' is known. The 'Id' will be unique to a single process, however, a 'Name', for example 'chrome', will bring back multiple processes for the Chrome web browser.

Get-Process -Id 3400
Get-Process -Name chrome

The 'Stop-Process' cmdlet, as the name suggests, can be used to stop one or more processes. If the 'Id' option is used, this will stop a single process. Using the 'Name' option may stop more than one process if multiple processes share the same name, for example, if the Chrome web browser is running there are likely to be multiple processes with the name 'chrome', so all would be stopped, which would have the effect of closing the application. This is the equivalent of doing 'End Task' in 'Task Manager'.

Stop-Process -Name chrome

There is also a 'Start-Process' cmdlet, which, in the below example would open up a new instance of the 'Notepad' application.

Start-Process -PassThru notepad

If system services need to be dealt with via the command line, PowerShell provides a number of cmdlets to achieve this. Firstly, the 'Get-Service' cmdlet, used on its own will list all services regardless of their status.

Get-Service

If the name of the service is known, this can be used to bring back just the details of the service with that name.

Get-Service -Name Spooler

In order to list just the running services, the 'Get-Service' cmdlet needs to be used in conjunction with 'Where-Object'. Services with other statuses can be returned in a similar manner.

Get-Service | Where-Object Status -eq Running

If it is necessary to stop, start or restart a service, this can be achieved with 'Stop-Service', 'Start-Service' or 'Restart-Service' respectively.

Stop-Service -Name Spooler
Start-Service -Name Spooler
Restart-Service -Name Spooler

When handling a number of files, it can sometimes be useful to compress them in to one file. PowerShell can be used to both create and extract from a zip archive.

# Example paths and files.
$exampletPathSource = "C:\demo\";
$exampletPathDestination = "C:\demo2\";
$examplePathZip = "C:\temp\demo.zip";

# Create the zip archive file.
Compress-Archive -Path $exampletPathSource* -DestinationPath $examplePathZip -Force

# Extract the zip archive file.
Expand-Archive -LiteralPath $examplePathZip -DestinationPath $exampletPathDestination -Force

If a piece of code is repeated in a number of different scripts, it can be moved into a script on its own and then included where needed in other scripts. This can be done using relative or absolute paths to the script to be included. In PowerShell this is known as dot sourcing.

In the below examples double quotes are used around both the relative and absolute paths, however, these are only necessary where there is a space in a folder or file name.

# Include another script using a relative path.
. ".\includes\demo-include.ps1"

# Include another script using an absolute path.
. "C:\demo\includes\demo-include.ps1"

It is possible to find files containing specified text. Here, the current directory, along with any sub-directories, are searched for files containing the word 'Test', and the path to each file is displayed.

Get-ChildItem -Recurse | Select-String "Test" -List | Select Path

This lists all files modified in the last 30 days, within a directory called 'Demo', including any sub folders there may be.

Get-ChildItem -Path "C:\Demo" -Recurse `
    | Where-Object -FilterScript { $_.LastWriteTime -ge (Get-Date).AddDays(-30) }

This lists all files modified after the specified date and time, within a directory called 'Demo', including any sub folders there may be.

Get-ChildItem -Path "C:\Demo" -Recurse `
    | Where-Object -FilterScript { $_.LastWriteTime -gt (Get-Date '09 May 2021 14:00') }

This lists all enabled local users on the current machine, with their local group membership.

# Retrieve enabled local users.
$Users = Get-LocalUser | Where Enabled -eq True

# Display the enabled users.
ForEach ($User in $Users)
{

    Write-Host "Enabled User: $User"

    # Retrieve the local groups for the user.
    $Groups = Get-LocalGroup `
        | Where-Object { (Get-LocalGroupMember $_).name -eq "$env:COMPUTERNAME\$User" }

    # Display the local groups for the user.
    ForEach ($Group in $Groups)
    {

        Write-Host "Group membership: $Group"

    }
}

A text file can be read from and processed line by line.

# File to read.
$file = "c:\demo\demo.txt"

# Process the file line by line.
foreach ($line in Get-Content $file) {

    # Display the line of text.
    Write-Host $line

}

Sometimes it is useful to know exactly where you are in the file system whilst in a terminal. This can be achieved using the 'Get-Location' cmdlet.

Get-Location

In order to move location, there is a corresponding 'Set-Location' cmdlet.

Set-Location C:\Windows\System32

If it is desirable to keep a track of the locations where you have been in a terminal so that you can return to previous locations, there are cmdlets to achieve this, 'Push-Location' and 'Pop-Location'. Using 'Push-Location' with no additional parameters will add the current working directory to a stack. Using this cmdlet and specifying a path will not only add the current working directory to a stack but move to the specified path in a similar manner to using 'Set-Location'.

Push-Location C:\demo

Repeating this once more will again add the current working directory to the top of the stack. When required to retrace the steps taken backwards, the 'Pop-Location' cmdlet can be used to return to the working directory at the top of the stack, removing it from the stack in the process.

Pop-Location

This can be repeated until the user has returned to their original location.

It is possible to add new content to a text file a line at a time. Note that if the text file doesn't already exist, it will get created at the time the first line of content is added.

# File to add content to.
$file = "c:\demo\demo.txt"

try
{

    # If file already exists, clear its contents.
    if (Test-Path $file)
    {
        Clear-Content $file
    }

    # Add 10 lines of content to the file.
    for ($i = 1; $i -le 10; $i++)
    {
        Add-Content $file "This is line $i."
    }

    # Confirm addition of content to file.
    Write-Host "Content added to file successfully."

}
catch
{

    Write-Host "Unable to write to file."

}