--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


Recently Changed Pages:

View All Pages

View All Tags


WIKI Disclaimer: As with most other things on the Internet, the content on this wiki is not supported. It was contributed by me and is published “as is”. It has worked for me, and might work for you.
Also note that any view or statement expressed anywhere on this site are strictly mine and not the opinions or views of my employer.

Pages with comments

View All Comments


Cheat Sheet

An overview of all sorts of commands and script usage.
Best practices and Styling

Most Used

PowerShell History

View history of powershell commands and invoke them using “r #”
<# Output #>
r 1

See all saved commands in vscode
code (Get-PSReadLineOption).HistorySavePath

PowerShell If

If statement
if (($alllogs -eq "True") -AND ($result)){
    Write-Host "Both statements are true"
}elseif (($buildreason -eq "IndividualCI") -or ($buildreason -eq "BatchedCI") -or ($buildreason -eq "PullRequest")){
    Write-Host "At least one of the statements is true"
}else {
    Write-Host "None of the statements is true"

PowerShell Count

Count number of strings / objects
# string
$een = "een"
# Array
$twee = @("een","twee")

# string
$een = "een"
# Array
$twee = @("een","twee")

Measure-Object - Sometimes counting when there is only one item can fail, use measure-object instead.
$een = "een"
($een | Measure-Object).Count
$twee = @("een","twee")
($twee | Measure-Object).Count

Windows Service Management

Stop Windows Service
  1. # Stop the service while checking the state for x² seconds and kill it if that doesn't work
  2. Write-Host "Stopping Service: $servicename; Status: Initiating"
  3. $sleeper = 1
  4. while (((Get-Service -Name "$servicename").Status -ne "Stopped") -AND ($sleeper -lt 128)){
  5. if ($sleeper -eq 1){
  6. Stop-Service -Name "$servicename"
  7. } elseif ($sleeper -eq 32){
  8. Stop-Service -Name "$servicename" -Force -NoWait
  9. } elseif ($sleeper -eq 64){
  10. # Try to kill the process now
  11. $servicepid = (Get-CimInstance win32_service -Filter "Name = '$servicename'").ProcessId
  12. try{
  13. Stop-Process -id $servicepid -Force
  14. }catch{
  15. Throw "Stopping Service: $servicename; Stopping process: $servicepid; Status: Failed; Error: $($_.Exception.Message)"
  16. }
  17. }
  18. if ($alllogs -eq "True"){Write-Host "Stopping Service: $servicename; Sleeptime: $sleeper seconds"}
  19. Start-Sleep -Seconds $sleeper
  20. $sleeper = $sleeper * 2
  21. }

Restart all Windows Services
get-service -name grn* -ComputerName appprd02 | Restart-Service -Verbose

Start all stopped Windows Services
Get-Service -Name grn* -ComputerName appprd01,appprd02,appprd03,appacc01,appacc02,apptst01,apptst02,appdev01,appdev02 | Where-Object {$_.Status -eq 'Stopped'} | Start-Service -Verbose
Get-Service | where {($_.Status -eq 'Stopped') -and ($ -like 'Grn*') -and ($_.StartType -eq 'Automatic')} | Start-Service

Note: -ComputerName only works in PS 5

Install Windows Service depends on Powershell version
if ($($PSVersionTable.PSVersion).Major -eq 7){
    New-Service -Name $serviceName -BinaryPathName $binaryAppExecutable -StartupType "AutomaticDelayedStart" -Credential $appuserCredentials
}else {
    New-Service -Name $serviceName -BinaryPathName $binaryAppExecutable -StartupType "Automatic" -Credential $appuserCredentials
    sc.exe config $serviceName start= delayed-auto

Note: PS 5 does not understand the startuptype AutomaticDelayedStart

Delete Windows Service
sc.exe delete windows.service

Note: In cmd you can use sc, in powershell sc is an alias for set-content, so you need to use sc.exe

Windows IIS Management

Restart all App Pools
& $env:windir\system32\inetsrv\appcmd list apppools /state:Started /xml | & $env:windir\system32\inetsrv\appcmd recycle apppools /in

Note: This does not start stopped app pools

Restart all App Pools Remotely
$servers = 'web01','web02','web03'
Invoke-Command -ComputerName $servers { & $env:windir\system32\inetsrv\appcmd list apppools /state:Started /xml | & $env:windir\system32\inetsrv\appcmd recycle apppools /in }

Note:This does not start stopped app pools

Windows Certificates

View cert info
certutil -v -dump <path to cert>

Open Current User Certificate store:

Open Local Machine Certificate store:

Get specific details from specific certificates from a list of servers and export to csv
$servers = @("server1","server2","server3")
Invoke-Command -ComputerName $servers {Get-ChildItem Cert:\LocalMachine\My | where-object {(($_.DnsNameList -like  "*rabobank*") -OR ($_.Subject -like "*rabobank*"))} |select-object @{name="hostname";expression={$(hostname)}},DnsNameList,NotAfter,Thumbprint,Subject,Issuer,FriendlyName} | Export-Csv certs.csv -NoTypeInformation

Active Directory

Count all users in all departments
Get-ADUser -SearchBase "OU=Users,DC=GetShifting,DC=local" -filter * -Properties name,department,enabled  | where {$_.enabled -eq "true"} | group department | select name, count

All enabled users that have never logged
Get-ADUser -Filter {(lastlogondate -notlike "*" -AND enabled -eq "True")} -SearchBase "OU=Users,DC=GetShifting,DC=local"

All enabled users that have not logged on for more than 90 days
$90Days = (get-date).adddays(-90)
Get-ADUser -Filter {(lastlogondate -le $90days -AND enabled -eq "True")} -SearchBase "OU=Users,DC=GetShifting,DC=local"

All servers
Get-ADComputer -Filter {(operatingSystem -like "*windows*Server*")}

Note: Does not select Windows 2000 Servers.

Select servers on properties
Get-ADComputer -filter {(description -like "*financial*" -AND name -like "SQL*")} -Properties * | select name, description

PowerShell Dates

# Dates
$timestamp = Get-Date -format "" # 20211011-14.27
$readdate = Get-Date -format "d MMM yyyy" # 11 Oct 2021
$weekdate = Get-Date -uformat %V # Week number # 41
$monthdate = Get-Date -format "MMMM-yyyy" # May-2021


Reverse loopup with ping
ping -a

NSlookup with default nameserver
nslookup servername

NSlookup with non-default nameserver ns01
nslookup servername ns01

Remote desktop console
mstsc.exe /v:servername /admin 

Test connection
Test-NetConnection -InformationLevel "Detailed" -Computername $host

PowerShell Input and Output

Try Catch Error Finally with LineNumber for troubleshooting
  1. function Get-ScriptLineNumber {
  2. return $MyInvocation.ScriptLineNumber }
  3. try{
  4. Write-Host "Do something that you want to catch the error of"
  5. }catch{
  6. # Catch the error
  7. Write-Host "Full Error: $_"
  8. # Or error out after all
  9. Throw "Failed on: $actionname; Status: Failed; Line: $(Get-ScriptLineNumber); Error: $($_.Exception.Message)"
  10. }finally {
  11. <#Do this after the try block regardless of whether an exception occurred or not#>
  12. # For example, clean up remote ps sessions
  13. }

Enable logging of script
  1. ### Script Variables ###
  2. $scriptname = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString())
  3. $scriptlocation = Split-Path $myinvocation.mycommand.path
  4. $date = (Get-Date).ToString('yyyyMMdd-HHmm')
  6. ### Start transcript for full logging capabilities ###
  7. start-transcript -path "$scriptlocation\$scriptname-$date-logtranscript.txt"
  9. ### Stop transcript
  10. Stop-transcript

Script output and Write-Host options
  1. # Inside a function use return or write-output
  2. return "value"
  3. Write-Output $value
  4. # Output an object without adding it to the function output
  5. Write-Host "color" -ForegroundColor Red -BackgroundColor green -noNewLine
  6. $object | Out-Host

Input password
$password = Read-Host "Enter password" -asSecureString

Use padright to fill a line with one symbol
Write-Host ''.PadRight(78, '=')
# Or with a variable
$wide = 32
Write-Host ''.PadRight($wide, '=')

Output in Azure DevOps

Logging output
# Logging output in azure devops
##[group]Beginning of a group - white 
##[warning]Warning message - orange 
##[error]Error message - red 
##[section]Start of a section - green 
##[debug]Debug text - purple 
##[command]Command-line being run - blue 
##[endgroup] - green 
Write-Host "`n##[section]Function: $($MyInvocation.MyCommand).`n"

Log error or warning
Write-Host "##vso[task.logissue type=error]Something went very wrong."
Write-Host "##vso[task.logissue type=warning]Found something that could be a problem."

Generate extra output if debug mode is set
if ($env:SYSTEM_DEBUG -eq "True"){$headers | Out-Host}

Remote PowerShell

Set variables
  1. $AdminCredentials = Get-Credential
  2. $remotePort = 5986
  3. $pso = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
  4. $Culture = "en-US"
  5. $pso.Culture = $Culture
  6. $pso.UICulture = $Culture
  7. $sessionParams = @{}
  8. $sessionParams.Add('UseSSL', $true)
  9. $sessionParams.Add('Port', $remotePort)
  10. $sessionParams.Add('Credential', $AdminCredentials)

Start session to restart computer
$session = New-PSSession -ComputerName webserverdmz.domain -EnableNetworkAccess -SessionOption $pso @sessionParams
Invoke-Command -Session $session -ScriptBlock {Restart-Computer}
Remove-PSSession $session

PowerShell Variables

Set system (environment) variable

Get all system (environment) variables, sorted by name
get-childitem -path env:* | Sort Name

Variables in function
Declare a variable with script scope to use it in a function
$script:orgUrl = ""
$script:apiversion = "api-version=6.0"
function SetBuildTag {
  # Load Azure DevOps API settings
  foreach ($tag in $tags){
      $tagurl = "$orgUrl/$env:System_Teamproject/_apis/build/builds/$env:BUILD_BUILDID/tags/$($tag)?$apiversion"

Variables in Azure DevOps

Pipeline variable in yaml - without PowerShell
  - name: BuildConfiguration
    value: 'Release'
- task: DotNetCoreCLI@2
  displayName: "Build Solutions"
    command: 'build'
    projects: '**/*.sln'
    arguments: '--no-restore --configuration $(BuildConfiguration)'

Pipeline parameter in yaml
if ( "${{ parameters.alllogs }}" -eq "True" ){write-Host "Parameter from pipeline"}

System variable in yaml
Variables can be used like system environment varriables

if (Test-Path "$env:Build_SourcesDirectory\$env:Build_Repository_Name\appsettings.Development.json"){Write-Host "System / Environment Variable"}
$sites = get-childitem -path env:* | Where-Object {$ -like "*-SiteName"} | Select-Object -ExpandProperty value # Added through Variable Group

Variables can also be used like pipeline variables

get-childitem $(Pipeline.Workspace) 
$dbserver = "$(serverDb)" + "." + "$(dnsZone)" # from Azure App Configuration

Variables in PS scriptfile
$adserver = $env:adServer + "." + $env:domain # from Azure App Configuration
$projects = Get-ChildItem -Path "$env:Build_SourcesDirectory\$env:Build_Repository_Name\deploy\" -Directory | Select-Object Name

Docker Containers

Show running container
docker ps
# or
docker container ls

Show all containers
docker ps -a

docker stop/start/restart containers
docker stop container_id
# default grace time = 10
docker stop --time=5 container_id 
docker start container_id
# Restart apache container by name
docker container restart httpd_web

Get docker container info
docker inspect container_id

Get docker container compose info
docker inspect container_id | grep com.docker.compose

Work in a container
docker exec -it container_id /bin/bash

Linux Bash

grep file without empty lines and comments
grep -v '^\s*$\|^\s*\#' postgresql.conf

find file in current and subdirectories
sudo find . -name


PowerShell Function Template

See here for guidelines.
function Use-AzureDevOpsApi{ #Use Get-Verb for a list of approved verbs
        Short description
        Long description
        Explain the parameter Pat. Repeat for additional parameters.
        Explain the powershell output, if any
        Pipeline example:
        - task: PowerShell@2
          displayName: "Use Default SystemAccessToken" 
            SYSTEM_ACCESSTOKEN: $(System.AccessToken) 
            pwsh: true
            targetType: 'inline'
            script: |
                # Load Azure DevOps API settings
        Script example:
        Use-AzureDevOpsApi -Pat $Pat
        System access token:
        Author : Sjoerd Hooft
        Version: 2022-08-03 
    param (
        [ValidateLength(52,52)] # See for more paramater validation 
        [ValidateSet("dev", "tst", "acc")]
    BEGIN {
        if ($alllogs -eq "True"){
            Write-Host "`n##[section]Function: $($MyInvocation.MyCommand).`n"
            Write-Host "Input: Package: $package; Feed: $feed; View: $view; environment: $environment"
        # Collect information
        # Do stuff
    END {
        # Cleanup

PowerShell Modules

Check Azure powershell module depending on PS version
  1. Write-Host "Check required PowerShell Modules `n"
  2. # The "new" PS module for Azure requires PowerShell 7
  3. if ($($PSVersionTable.PSVersion).Major -eq 7){
  4. if (Get-Module -ListAvailable -Name AZ) {
  5. Write-Host "PowerShell module Azure exists"
  6. } else {
  7. Write-Host "PowerShell module Azure does not exist. Start installation. "
  8. Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
  9. }
  10. }else{
  11. Throw "Powershell needs to be version 7"
  12. }

PowerShell DNS Module
if (Get-Module -ListAvailable -Name DnsServer) {
    Write-Host "PowerShell module DnsServer exists"
} else {
    Write-Host "Module DNSServer does not exist. Starting installation"
    Import-Module ServerManager
    Add-WindowsFeature -Name "RSAT-DNS-Server"

PowerShell AD Module
# Because ActiveDirectory is a 5.1 module you need to add -All 
if (Get-Module -ListAvailable -All -Name ActiveDirectory) {
    Write-Host "PowerShell module ActiveDirectory exists"
} else {
    Write-Host "Module ActiveDirectory does not exist. Starting installation"
    Import-Module ServerManager
    Add-WindowsFeature -Name "RSAT-AD-PowerShell" –IncludeAllSubFeature

PowerShell Pester module, remove shipped version and install latest version (Needs PS 7)
  1. if (Get-Module -ListAvailable -Name Pester) {
  2. # Check for version 3.4 and if available remove it
  3. Get-Module -ListAvailable -Name Pester
  4. if (((((Get-Module -ListAvailable -Name Pester).Version).Major) -eq 3) -AND ((((Get-Module -ListAvailable -Name Pester).Version).Minor) -eq 4)) {
  5. Write-Host "PowerShell Module Pester is version 3.4 which is shipped along with Win10/Windows 2016. Start removal:"
  6. $module = "C:\Program Files\WindowsPowerShell\Modules\Pester"
  7. takeown /F $module /A /R
  8. icacls $module /reset
  9. icacls $module /grant "*S-1-5-32-544:F" /inheritance:d /T
  10. Remove-Item -Path $module -Recurse -Force -Confirm:$false
  11. }
  12. # Verifieer of Pester al aanwezig met minimaal versie 5
  13. if ((((Get-Module -ListAvailable -Name Pester).Version).Major) -ne 5) {
  14. Write-Host "PowerShell module Pester is not up to date"
  15. Install-Module -Name Pester -Force -Scope CurrentUser
  16. }else{
  17. Write-Host "PowerShell Module Pester is available with minimal version of 5:"
  18. Get-Module -ListAvailable -Name Pester
  19. }
  20. } else {
  21. Write-Host "PowerShell module Pester does not exist. Start installation. "
  22. Install-Module -Name Pester -Force -Scope CurrentUser
  23. }

IIS Administration Module, install extra version, see the version and the available commandlets. Note that this needs to be done in PowerShell 5 Administrative Shell
Install-Module -Name IISAdministration -Scope AllUsers -Force #Installs latest version next to it (
Import-Module IISAdministration -RequiredVersion
$mod = Get-Module -Name IISAdministration
$mod.ExportedCmdlets | Format-Table

Import PS Module
Import-Module Pester

Get commands within a module
Get-Command -module Pester

Remove / Unload a PowerShell module
Remove-Module Pester

PowerShell ForEach

With custom PS Object and export to csv
  1. $myCol = @()
  2. foreach ($vm in (get-vmhost esxprd101.intranet | get-vm )){
  3. $VMInfo = "" | Select-Object VMName,VMHostName,NICCount
  4. $VMInfo.VMName = $vmview.Name
  5. $VMInfo.VMHostName = $vmview.Guest.HostName
  6. $VMInfo.NICCount = $vmview.Guest.Net.Count
  7. $myCol += $VMInfo
  8. }
  9. $myCol |Export-csv -NoTypeInformation $csvfile

PowerShell Comparison

# logical and comparison 
# -and, -or, -not , ! : Connect expressions 
# -eq, -ne : Equal, not equal 
# -gt / -lt, -ge / -le : Greater/less than, greater or equal / less or equal 
# -replace 
# -match / -notmatch : Regular expression match 
# -like / -notlike : wilcard matching 
# -contains / -notcontains : check for value in array: $array -contains $value
# -in / -notin : reverse syntax from contains: $value in $array 

PowerShell Location

Change directory (alias cd)
Set-Location c:\

Change directory and back
PS C:\Users\sjoer> Push-Location c:\
PS C:\> Pop-Location
PS C:\Users\sjoer>

Azure PowerShell

NOTE: Module AZ only works in PS 7

TLS version
# Set TLS version to use TLS 1.2 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Login and context
Get-AzContext -ListAvailable
Set-AzContext -Name $dtapEnvironment -Subscription $azureSubscriptionName

Get TenantId
$tenantId = (Get-AzContext).Tenant.Id

Get secret from KeyVault
$adadminpass = (Get-AzKeyVaultSecret -VaultName kv-operations-global -Name "adAdminPass").SecretValue

Set secret to KeyVault
$userpasswordsecure = ConvertTo-SecureString -String $userpassword -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName kv-operations-global -Name $username -SecretValue $userpasswordsecure

Windows Processes

Get all processes
$processes = Get-CimInstance -ClassName Win32_Process | Select-Object ProcessName,ProcessId,CommandLine,Path | sort processid

Kill a process
    $processid = (Get-CimInstance win32_process -Filter "Name = 'mmc.exe'").ProcessId
    if ($null -ne $processid){
        Stop-Process -id $processid -Force
    Write-Host "Error killing mmc: $_"

Windows CommandLine

Windows System

Collect uptime, patches, windows version and more

System Variables

Set an environment variable until the end of the current command prompt session
set AWS_DEFAULT_REGION eu-west-1

Set an environment variable in both the current command prompt session and all command prompt sessions that you create after running the command
setx AWS_DEFAULT_REGION eu-west-1

Windows GPO

Group policy result to html
gpresult /h gpreport.html

Local Group Policy editor

GPO Management console:

Force GPO update
gpupdate /force

Windows Shutdown

Reboot in 1 second
shutdown -r -t 1

Shutdown in 0 seconds (force option implied)
shutdown -s -t 0

Windows TCP Dump

Note: This needs (portable) tcpdump, the created file can be opened by (portable) wireshark for analysis. See here for more info on tcpdump.

dump traffic with host on interface 1 to file
\tcpdump.exe -i 1 -vv host -w tcpdumpfile.pcap 

dump traffic with host on interface 1 to file with a readable timestamp format
\tcpdump.exe -i 1 -vv host -tttt -nr tcpdumpfile.pcap 



Check git repository size
git count-objects -vH 

Combine fetch and merge to completely update a repository
git pull 
You could leave a comment if you were logged in.
cheatsheet.txt · Last modified: 2022/11/18 13:24 by sjoerd