Powershell
Profiles
Directory that contains Profiles
Get-ChildItem ~\Documents\WindowsPowershell\
Possible output for Terminal, ISE and VS Code
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/29/2023 11:08 AM 172 Microsoft.PowerShellISE_profile.ps1
-a---- 7/29/2023 11:12 AM 1170 Microsoft.PowerShell_profile.ps1
-a---- 7/29/2023 11:08 AM 158 Microsoft.VSCode_profile.ps1
Find all profiles or currently used Profile with:
$PROFILE | Select-Object *
$PROFILE | Select-Object CurrentUserCurrentHost
Shutdown the Computer
use shutdown or stop-computer
shutdown /s /t 0
Stop-Computer
Restart the Computer
Restarts the Computer with Other(plenned) reason
shutdown /r /d p:0:0
SSH Sessions with Posh
This starts a new SSH Session through Powershell to a linux computer
New-SSHSession -Computername <IP or DNS> -Port 443 -KeyFile C:\path\to\key\file -Credential <username>
Get-SSHSession
Invoke-SSHCommand -SessionId 0 -Command "ls -lah"
Remove-SSHSession -Index 0 -Verbose
ssh keys
Windows/powershell does not interpret ~
use $HOME
instead and backward slashes For some reason private ssh keys need to have an empty new Line at the end of the file
ssh-keygen -t rsa -b 2048 -C "comments" -f $HOME\.ssh\keyname -N ""
Permissions
If permissions on the ssh key file are not right:
$path = "$HOME\.ssh\keyname"
icacls $path /inheritance:r # Remove inherited permissions
icacls $path /grant:r "$($env:USERNAME):(F)" # Give full access to current user only
icacls $path /remove:g "BUILTIN\Users" # Remove access for 'BUILTIN\Users' group
Installing the Linux Support thing for Windows
Install Ubuntu WSL https://docs.microsoft.com/en-us/windows/wsl/install-win10 It can be started by typing bash
in Powershell Run this, and only this as Administrator/root
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Run the following as regular User so you don't need to be Administrator to use wsl this installs Ubuntu 18-04. Look here for current supported distros and manual download Links wsl
Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1804 -OutFile Ubuntu.appx -UseBasicParsing
Rename-Item Ubuntu.appx Ubuntu.zip
Expand-Archive Ubuntu.zip Ubuntu
cd Ubuntu
.\ubuntu1804.exe
If WSL is already installed or to install any distro run
wsl --install -d Ubuntu-22.04
to reinstall a distribution run:
wsl --unregister Ubuntu-22.04
File Actions
Find, seek and destroy
Finding Files and Displaying only the Filenpath and name one per Line
Get-ChildItem -Path *Filename* -Recurse | select FullName
Search in Files
Search for a string within a Folder and its subfolders
Get-ChildItem -Recurse | Get-Content -ErrorAction SilentlyContinue | Select-String -pattern "error" | Out-File Errors.log
Delete
Delete a folder that is not empty
Remove-Item -Force -Recurse '<path with spaces>\'
ri -Force -Recurse C:\Users\<user>\<path>
Recurse through a directory structure and search each files for pattern
then store each match in a hash-table/dictionary with the Filename as key and a number per match.
$w = @{}
foreach( $file in Get-ChildItem -Recurse ){
$ma = Get-Content -Path $file -ErrorAction SilentlyContinue | Select-String -pattern "pattern"
$ma
$i = 0
foreach ( $match in $ma ){
$i += 1
$file.Name + "_" + $i
$w.Add( $file.Name + "_" + $i, $match )
}
}
String Actions
Base64 en- and decoding
[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("https://lib.rjo.me"))
aHR0cHM6Ly9saWIucmpvLm1l
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("aHR0cHM6Ly9saWIucmpvLm1l"))
https://lib.rjo.me
Path actions
print PATH one entry per line
($env:PATH).split(";")
Create a range object and search through a filetree for a string that contains elements of that range
$a = 1..22
$a | ForEach-Object { @{(Get-Content .\NoErrorFiles.log | Select-String ('5/' + $_ + '/19') | Measure-Object).Count = '5/'+$_+'/19'}}
Compare aka diff two files
It has to explicitly taken the content of the files. If just two filenames are given, those are compared without regard of their actual content.
Compare-Object $(Get-Content .\first.txt) $(Get-Content .\second.txt)
Compare Errors from to Error Log files
The following creates a table named "TableName" and add the 3 columns Date,Error1 and Error2 to it. Then it populates the table with the findings of the Files.
$table = New-Object SYStem.Data.DataTable "TableName"
$col1 = New-Object system.Data.DataColumn Date,([string])
$col2 = New-Object system.Data.DataColumn Error1,([string])
$col3 = New-Object system.Data.DataColumn Error2,([string])
$table.Columns.Add($col1)
$table.Columns.Add($col2)
$table.Columns.Add($col3)
1..28 | ForEach-Object { $row=$table.NewRow(); $row.Date=('5/'+$_+'/19'); $row.Error1=(Get-Content .\Errorlogs1.log | Select-String ('5/' + $_ + '/19') | Measure-Object).Count; $row.Error2=(Get-Content .\Errorlogs2.log | Select-String ('5/' + $_ + '/19') | Measure-Object).Count; $table.Rows.Add($row)}
Chocolatey
Getting chocolatey up and running with Powershell V5
Find-Package -Provider chocolatey
And Install it
Find-Package -Provider chocolatey -name openssl | Install-Package
Active Directory
On a Windows 2016 Server the RSAT Tools need to be installed, you can find it with the Powershell Commands below.
Get-WindowsOptionalFeature -Online -FeatureName *RSAT*
Enable-WindowsOptionalFeature -Online -FeatureName RSAT-ADDS-Tools-Feature -All
Get-WindowsFeature RSAT*
Install-WindowsFeature RSAT-AD-Powershell
Get-ADComputer
Query for Computers with names like appsrv and display only the found names one per line
Get-ADComputer -Filter 'Name -like "appsrv*"' | select Name
Get all Computer start contain xyz but do not start with abc
Get-ADComputer -Filter {(Name -like "*xyz*") -and (Name -notlike "abc*")} | select Name
Get-ADUser
Get all Groups a User is Member of and store them in a variable
$GAwesome = (Get-ADPrincipalGroupMembership -Identity ((Get-ADUser -filter "Name -like 'Guy Awesome'").ObjectGUID)).Name
I had some problems using the Get-ADGRoupMember cmdlet with an ObjectGUID for the -Idetity Parameter. Working around that I could use the Get-ADGroup cmdlet in the following way.
(Get-ADGroup '534867fb-57b0-471f-85bf-b30a8900009a1' -Properties members).Members
Get everything about a User
Get-ADUser -Identity<Username> -Properties *
Getting a list of all locked out accounts
(Get-ADUser -Filter * -Properties lockedOut,GivenName | Where {$_.LockedOut -eq $True}).Name
Get Alls Users in a company
Get-ADUser -Filter * -SearchBase "OU=<users>,OU=<company>,DC=<domain>,DC=com" | Measure-Object
Get-ADUser -Filter * -SearchBase "OU=Users-Disabled,OU=Users,OU=<company>,DC=<domain>,DC=com" -Properties LastLogonDate | select Name,LastLogonDate | Sort-Object -Property LastLogonDate
Adsisearcher
When the RSAT-AD-Powershell
module is not available adsisearcher
can help.
(([adsisearcher]"samaccountname=ME988789").FindAll() | select -ExpandProperty properties).memberof | sort
Getting all Users currently logged in to a machine/server
$ gwmi Win32_LoggedOnUser | select Antecedent
query users
Add-ADGRoupMember
To add a user to an Active Directory Group user as in the Microsoft Docs
Add-ADGroupMember -Identity anygroup -Members anyuser
Copy Files Remotely
Copy Files from a Remote Machine
Copy Files from a to/from a remote Server by instatiating a new PSSession and then use the -ToSession/-FromSession
Flag use the -Recurse Flag to copy more than one File. I did not try to copy it directly from the remote machine to the other remote machine. I assume this wouldn't work due to the second hop Problem.
$ASession = New-PSSession -ComputerName <Remote-Name> -Credential (Get-Credential)
Copy-Item "E:\<path_name>*" -Destination "<local-path>" -Recurse -FromSession $ASession
$BSession = New-PSSession -ComputerName <Remote-Name> -Credential (Get-Credential)
Copy-Item "<local-path>\Test.z*" -Destination "<remote-path>" -Recurse -ToSession $BSession
Get all commands from Module
(Get-Module (get-command -name <cmdlet>).source).ExportedCommands
This command gets the Module containing the and then gets all the commands in that Module
Firewall Rules with Powershell
Get-NetFirewallRule
Remove-NetFirewallRule
New-NetFirewallRule -name "Allow inbound 8080" -DisplayName "Allow inbound 8080" -protocol tcp -Enabled true -RemoteAddress 123.456.789.012 -profile domain -action allow -remoteport 8080 -localport 8080
The name parameter has to be unique to the Firewall Rule, the DisplayName can be the same across several Firewall Rules, and therefore used to group Rules together.
Connection Security Rules
Connection Security Rules can be found at Control Panel > System and Security > Windows Defender Firewall > Advanced Settings > Connection Security Rules
New-NetIPsecRule -IPsecRuleName "Rule Name" -DisplayName "Rule Display Name" -Enabled True -LocalAddress <Ip-Address> -LocalPort <Ports> -Protocol TCP
Notes:
The IpSecRuleName must be unique
Ports can be
A Single Port e.g. 80
A range of Ports e.g. "80-443"
A list of Ports e.g. 80,443,8080
Select-String
Find in all Files starting with TMP the regex Pattern and print only the found Matches. Searching for content within the matching Files.
Select-String -Path "C:\<Path>\TMP*" -Pattern "regex" | ForEach-Object {$_.Matches[0].Value}
Windows Event Log
All Sources
To get a list of all available Sources, run the following. You can substitue Application with System,Setup,Forwarded Events or Security also you need Administrator Rights to access Security Logs.
$Sources=(Get-Eventlog -LogName Application).Source
[System.Collections.ArrayList]$SourceNames= @{}
foreach ($source in $Sources) {
if ($SourceNames -notcontains $source) {
[void]$SourceNames.add($source)
}
}
$SourceNames
The [void] prevents $SourceNames
from containing the index numbers of its content.
PSReadline
Using PSReadline for better (bash-like) history. Docs
Last updated