Reading PowerShell for Sysadmins by Adam Bertram from No Starch Press (among other sources) and taking notes.

Get-Alias

Use Get-Alias to show Windows CLI commands that work in PowerShell.

Get-Alias | findstr dir

Pipe to findstr to filter output.

Get-Command

Use Get-Command to see a list of every command PowerShell is aware of by default.

Get-Command -Verb Get
Get-Command -Verb Get -Noun Content
Get-Command -Noun Content

Specify commands that include specific verbs or nouns to filter the output of Get-Command to find the command that you need.

Update-Help

Download new man page content.

Get-Help Get-ChildItem
Get-Help Get-ChildItem -Examples
Get-Help Get-ChildItem -Detailed
Get-Help Get-ChildItem -Full

Read the manual!

Get-Help Set-StrictMode -online

Open the help document on the Microsoft website for a specific command.

PS C:\> Get-Help -Name About

Name                              Category  Module                    Synopsis
----                              --------  ------                    --------
about_BeforeEach_AfterEach        HelpFile                            performed at the beginning and end of every It...
about_Mocking                     HelpFile                            Pester provides a set of Mocking functions mak...
about_Pester                      HelpFile                            Pester is a BDD based test runner for PowerShell.
about_should                      HelpFile                            Provides assertion convenience methods for com...
about_TestDrive                   HelpFile                            A PSDrive for file activity limited to the sco...

Search Help Files by name.

Get-Help -Name * | findstr About

Show all Help Files and filter output.

Get-History

Show the command history for the current shell session. You can also use the alias history.

PS C:\> $MaximumHistoryCount
4096

The max history count is set with the $MaximumHistoryCount variable.

Set-StrictMode -Version Latest

Turn on StrictMode to make PowerShell enforce good coding practice.

$hostname = 'PC1'

Set a variable in PowerShell.

Set-Variable -Name hostname -Value PC1

An alternative way to set a hostname.

PS C:\> Write-Host "Now installing software package to $hostname"
Now installing software package to PC1

PS C:\> Write-Host 'Now installing software package to $hostname'
Now installing software package to $hostname

Use single quotes for the shell to take input literal. Use double quotes to allow for shell interpretation. Either single or double quotes will set a string variable.

Get-Variable

Show all available variables in current shell session.

$ass = $null

Use the $null to create a variable without assigning any value.

$LASTEXITCODE

The $LASTEXITCODE automatic variable shows the exit code of the last run command.

PS C:\> ping 8.8.8.8 -n 1

Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=13ms TTL=111

Ping statistics for 8.8.8.8:
	Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
	Minimum = 13ms, Maximum = 13ms, Average = 13ms
PS C:\> $LASTEXITCODE
0
PS C:\>

0 = success 1 = failure

$ErrorActionPreference = 'SilentlyContinue'

Set the $ErrorActionPreference automatic variable to change to action resulting from a failed command.

PS C:\> Get-Variable -Name *Preference

Name                           Value
----                           -----
ConfirmPreference              High
DebugPreference                SilentlyContinue
ErrorActionPreference          Continue
InformationPreference          SilentlyContinue
ProgressPreference             Continue
VerbosePreference              SilentlyContinue
WarningPreference              Continue
WhatIfPreference               False

Modify other preference variables as needed.

[Int32]$Var1 = 32
[Float]$Var2 = 325.1243324242
[Double]$Var2 = 325.1243324242
[String]$Var3 = batman

Use [Int32], [Float], [Double], and [String] to force PowerShell to set certain types of variables—usually PowerShell will automatically set the correct data type.

PS C:\> $hosts=@(“PC1”, “PC2”, ”PC3”, ”PC4”)
PS C:\> $hosts.Length

Length property.

PS C:\> $hosts | Sort-Object  -Property Name -Descending
PC3
PC4
PC1
PC2

Sort Method.

PS C:\> $hostname = “PC99823”
PS C:\> $hostname.Remove(5)
PC998
PS C:\> $hostname.Remove(3,4)
PC9

Remove characters from a string by using the Remove() method.

$hostsfile = Get-Content $env:SystemRoot\System32\Drivers\etc\hosts

Read a text file to a variable.

$hostsfile = Get-Content $env:SystemRoot\System32\Drivers\etc\hosts | Where { $_ -notmatch "#" }

Read a file to varibale and remove all lines that start with a certain character.

if (-not(Test-Path -Path $env:SystemRoot\System32\Drivers\etc\hosts.orig)) {
Copy-Item $env:SystemRoot\System32\Drivers\etc\hosts -Destination $env:SystemRoot\System32\Drivers\etc\hosts.orig
}

Check if file exists and take action if not.

(Get-Content  file.txt) | ? { -not [String]::IsNullOrWhiteSpace($_) } | Set-Content file.txt

Strip blank lines from text file.

$PCs = @(‘host1’,’host2’,’host3’,’host4’,’host5’)

Create a new array.

$PCs = @()

Create an empty array.

$PCs += ‘host1’

Add an element to an array.

$PCs += @(‘host1’,’host2’)  

Add multiple elements to an array.

$PCs[2]  

Address an element in an array.

$PCs[0..3]

Address multiple elements in an array.

$PCs[3] = ‘host9’

Modify elements in an array.

$PCs = @("PCs[0]") 

Removing elements from an array—you can’t! Make a new array.

$software= [System.Collections.ArrayList]@('SPSS','ArcGIS','SAS','AutoCAD', ‘BonziBuddy’)

Use an ArrayList is you want to be able to delete elements!

$software.Add(‘WinAMP’)

Add to an ArrayList.

$software.Remove(‘BonziBuddy’)

Remove from an ArrayList.

$file = 'C:\Program Files\Common Files\Bentley Shared\CONNECTION Client\Bentley.Connect.Client.exe.config'
$find = '<add key="PopupIntervalMinutes" value="60" />'
$replace = '<add key="PopupIntervalMinutes" value="1440 " />'

Parse and replace text in a file.

$action = @(
	$(New-ScheduledTaskAction –Execute 'cmd.exe' -Argument '/c reg delete HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v "Bentley License Service" /f'), 
	$(New-ScheduledTaskAction –Execute 'cmd.exe' -Argument '/c reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "Bentley License Service" /f'),
	$(New-ScheduledTaskAction –Execute 'cmd.exe' -Argument '/c reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "MySELECT.exe" /f')
)

$trigger = @(
	$(New-ScheduledTaskTrigger -Daily -DaysInterval 1 -At 5am), 
	$(New-ScheduledTaskTrigger -Daily -DaysInterval 1 -At 5pm),
	$(New-ScheduledTaskTrigger -AtLogOn),
	$(New-ScheduledTaskTrigger -AtStartup)
)

Unregister-ScheduledTask -TaskName "NoAutoStart_Bentley_Connection_Client" -Confirm:$false -erroraction 'silentlycontinue'
New-ScheduledTaskPrincipal -UserId SYSTEM -RunLevel Highest
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "NoAutoStart_Bentley_Connection_Client" -Description "Disables Auto-Start of Bentley Connection Client" -user $user -RunLevel Highest

Create a scheduled task with one or more actions and one or more triggers.

Remove-ItemProperty HKLM\Software\Microsoft\Windows\CurrentVersion\Run -Name "Bentley License Service" -Force -erroraction 'silentlycontinue'

Delete a registry key value.

Remove-Item -Path C:\testfile1.txt -Force -erroraction 'silentlycontinue'

Delete a file.

Remove-Item -Path C:\scripts\*.* -Force -erroraction 'silentlycontinue'
Get-ChildItem -Path C:\scripts -File | Remove-Item -Verbose
Get-ChildItem -Path C:\scripts -File -Recurse | Remove-Item -Verbose

Delete multiple files from a folder.

Remove-Item -Path C:\scripts\* -Include *.bat
Get-ChildItem -Path C:\scripts\* -Include *.bat -Exclude *filename* | Remove-Item -Verbose

Delete multiple files from a folder including or excluding file types or file names.

$folder = 'C:\test'
get-acl $folder | select -expand access

Get folder permissions.

$folder = 'C:\test'
$identity = 'BUILTIN\Users'

$acl = Get-Acl -Path $folder
$permission = $identity, 'Read,Modify', 'ContainerInherit, ObjectInherit', 'None', 'Allow' 
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission
$acl.SetAccessRule($rule)
# Save the access rule to disk:
$acl | Set-Acl -Path $folder

Add read and modify access for BUILTIN\Users group.

$folder = 'C:\test'
$identity = 'BUILTIN\Users'

$acl = Get-Acl -Path $folder
$permission = $identity, 'Modify', 'ContainerInherit, ObjectInherit', 'None', 'Allow' 
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permission
$acl.RemoveAccessRule($rule)
# Save the access rule to disk:
$acl | Set-Acl -Path $folder

Remove modify access for BUILTIN\Users group.

Permissions options are: Read, Modify, and FullControl.

Inherited folder permissions options are:

ObjectInherit - This folder and files. (no inheritance to subfolders)
ContainerInherit - This folder and subfolders.
InheritOnly - The ACE does not apply to the current file/directory.

$file1ACL = get-acl c:\file1.txt
set-acl -path C:\file2.txt -AclObject $file1ACL

Copy the security settings from file1.txt to file2.txt

$PSVersionTable

Show the PowerShell version.

winget install --id Microsoft.Powershell --source winget

Install PowerShell 7 with winget

Get-ExecutionPolicy -List         

	Scope ExecutionPolicy
	----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    RemoteSigned

Shows the curret Scope and corresponding Policy 

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned 

Set a Process scope that only affects the current user. 

Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned 

Set a Process scope that only affects the current PowerShell session.


PowerShell for Sysadmins
https://nostarch.com/powershellsysadmins

SANS Pen Test Cheat Sheet: PowerShell
https://www.sans.org/blog/sans-pen-test-cheat-sheet-powershell/

An A-Z Index of Windows PowerShell commands
https://ss64.com/ps/

Official product documentation for PowerShell
https://learn.microsoft.com/en-us/powershell/

Installing PowerShell on Windows
https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3#install-powershell-using-winget-recommended

Set and Scope ExecutionPolicy
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-7.3