Powershell by example

User management
Network management and connectivity
Install and connect via SSH to Windows server
Service management
Customising your Powershell profile
Getting help on a command
Practical example: search for Windows updates pending install

User management

To create a local user in Powershell, let’s use the New-LocalUser command:

PS > New-LocalUser -Name 'george' `
	-Description 'Local admin.' `
	-Password (ConvertTo-SecureString -String 'somestring' `
	-AsPlainText -Force)

Name   Enabled Description
----   ------- -----------
george True    Local admin.

To add the new user to the local Administrators group, we can use Add-LocalGroupMember; -WhatIf does not run the command, it shows what would be done:

PS > Add-LocalGroupMember -Group "Administrators" -Member "george" -WhatIf
What if: Performing the operation "Add member WIN2022-1\george" on target "Administrators".

Network management and connectivity

To set a static IP address, let’s get the current IP address and network interface index InterfaceIndex:

PS > Get-NetIPAddress

IPAddress         : 192.168.1.101
InterfaceIndex    : 6
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Dhcp
SuffixOrigin      : Dhcp
AddressState      : Preferred
ValidLifetime     : 23:15:54
PreferredLifetime : 23:15:54
SkipAsSource      : False
PolicyStore       : ActiveStore

We can then set a local IP to the InterfaceIndex from the previous command:

PS > New-NetIPAddress -IPAddress 192.168.1.110 `
	-PrefixLength 24 -DefaultGateway 192.168.1.1 `
	-InterfaceIndex 6

IPAddress         : 192.168.1.110
InterfaceIndex    : 6
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Tentative
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 192.168.1.110
InterfaceIndex    : 6
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Invalid
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : PersistentStore

Let’s set the DNS server to the gateway IP:

PS > Set-DnsClientServerAddress -InterfaceIndex 6 -ServerAddresses ('192.168.1.1')

Let’s use Test-NetConnection to ping a web server; this tests name resolution via DNS:

PS > Test-NetConnection -ComputerName www.google.com

ComputerName           : www.google.com
RemoteAddress          : 172.217.169.68
InterfaceAlias         : Ethernet
SourceAddress          : 192.168.1.110
PingSucceeded          : True
PingReplyDetails (RTT) : 45 ms

Install and connect via SSH to Windows server

To connect to the server via SSH, we will need to install the OpenSSH.Server package first.
We can see that it is not yet installed:

PS > Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

Name  : OpenSSH.Client~~~~0.0.1.0
State : Installed

Name  : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

We will install it:

PS > Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

Path          :
Online        : True
RestartNeeded : False

We will then start and activate the Windows service:

PS > Start-Service sshd
PS > Set-Service -Name sshd -StartupType 'Automatic'

To connect from a linux machine, via the console, we will use the Windows user name/password and the Windows server IP address:

george@dom:~$ ssh george@192.168.1.110
george@192.168.1.110's password:

We are now connected to the Windows server via ssh, cmd.exe was started:

Microsoft Windows [Version 10.0.20348.587]
(c) Microsoft Corporation. All rights reserved.

george@WIN2022-1 C:\Users\george>

To launch Powershell, on the remote Windows machine, we can pass the option (-o RemoteCommand).
We also pass the -t parameter, so that tab completion works in the console:

george@dom:~$ ssh george@192.168.1.110 -t -o RemoteCommand="powershell.exe"
george@192.168.1.110's password:
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Users\george>

Service management

To get a list of Windows services:

PS C:\Users\george> Get-Service | Format-Table -AutoSize

Status  Name                                     DisplayName
------  ----                                     -----------
Stopped AJRouter                                 AllJoyn Router Service
Stopped ALG                                      Application Layer Gateway Service
Stopped AppIDSvc                                 Application Identity
Running Appinfo                                  Application Information
Stopped AppMgmt                                  Application Management
Stopped AppReadiness                             App Readiness

To list services that are currently running, we use Where-Object filter to search for items where the status is Running.
We also use Format-Table to autosize the columns, otherwise output will be truncated with ellipses.

PS > Get-Service | Where-Object {$_.Status -eq "Running"}|Format-Table -AutoSize

Status  Name                   DisplayName
------  ----                   -----------
Running Appinfo                Application Information
Running BFE                    Base Filtering Engine
Running BrokerInfrastructure   Background Tasks Infrastructure Service
Running camsvc                 Capability Access Manager Service
Running cbdhsvc_281f3          Clipboard User Service_281f3
Running CDPSvc                 Connected Devices Platform Service
Running CDPUserSvc_281f3       Connected Devices Platform User Service_281f3
Running CoreMessagingRegistrar CoreMessaging

To find more information about a service, we can specify its name:

PS > Get-Service "sshd"

Status   Name               DisplayName
------   ----               -----------
Running  sshd               OpenSSH SSH Server

To stop a service, we use Stop-Service:

PS > Stop-Service "sshd"
PS > Get-Service "sshd"

Status   Name               DisplayName
------   ----               -----------
Stopped  sshd               OpenSSH SSH Server

To start it again:

PS > Start-Service "sshd"
PS > Get-Service "sshd"

Status   Name               DisplayName
------   ----               -----------
Running  sshd               OpenSSH SSH Server

Customising your Powershell profile

We can customise Powershell to run certain commands at initialisation.
This is useful if you want to change to the home directory automatically, to set variables. We can use $PROFILE to show our current profile location:

PS C:\Users\george> $PROFILE
C:\Users\george\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

We edit the file Microsoft.PowerShell_profile.ps1 and we can for example, clear the screen of any messages and change to the user’s home folder ~.

$global:FormatEnumerationLimit=-1
Clear-Host
Set-Location ~

FormatEnumerationLimit will not truncate elements in the list, for example PSCompatibleVersions will show all its elements:

PS C:\Users\george> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.20348.558
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.20348.558}
BuildVersion                   10.0.20348.558
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Getting help on a command

If we want to get more information on a Powershell command, we can use Get-Help < command >:

PS > Get-Help Add-LocalGroupMember

NAME
    Add-LocalGroupMember

SYNOPSIS
    Adds members to a local group.

Practical example: search for Windows updates pending install

$session = New-Object -com "Microsoft.Update.Session"
$searcher = $session.CreateUpdateSearcher()
$results = $searcher.search("IsInstalled=0")

We can then show only the title of the updates:

PS > $results.Updates|Select-Object -ExpandProperty "Title"
2022-02 Cumulative Update Preview for .NET Framework 3.5 and 4.8 for Microsoft server operating system version 21H2 for x64 (KB5010475)
2025-01 Cumulative Update for .NET Framework 3.5, 4.8 and 4.8.1 for Microsoft server operating system version 21H2 for x64 (KB5050187)
Windows Malicious Software Removal Tool x64 - v5.132 (KB890830)
Security Intelligence Update for Microsoft Defender Antivirus - KB2267602 (Version 1.423.276.0) - Current Channel (Broad)
2025-02 Cumulative Update for Microsoft server operating system version 21H2 for x64-based Systems (KB5051979)