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.ps1Find all profiles or currently used Profile with:
$PROFILE | Select-Object *
$PROFILE | Select-Object CurrentUserCurrentHostShutdown the Computer
use shutdown or stop-computer
/sflag for shutting down/tflag delays shutdown for xx seconds (3600s = 1h, 14400s = 4h)/aflag aborts a shutdown (also seems to work for forced updates and maintenance)
shutdown /s /t <seconds>
Stop-Computer
shutdown /aRestart the Computer
Restarts the Computer with Other(planned) reason
shutdown /r /d p:0:0SSH 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 -Verbosessh 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' groupInstalling 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-LinuxRun 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.exeIf WSL is already installed or to install any distro run
wsl --install -d Ubuntu-22.04to reinstall a distribution run:
wsl --unregister Ubuntu-22.04File Actions
Find, seek and destroy
Finding Files and Displaying only the Filenpath and name one per Line
Get-ChildItem -Path *Filename* -Recurse | select FullNameSearch 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.logDelete
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.mePath 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 chocolateyAnd Install it
Find-Package -Provider chocolatey -name openssl | Install-PackageActive 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-PowershellGet-ADComputer
Query for Computers with names like appsrv and display only the found names one per line
Get-ADComputer -Filter 'Name -like "appsrv*"' | select NameGet all Computer start contain xyz but do not start with abc
Get-ADComputer -Filter {(Name -like "*xyz*") -and (Name -notlike "abc*")} | select NameGet-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)).NameI 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).MembersGet 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}).NameGet 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 LastLogonDateAdsisearcher
When the RSAT-AD-Powershell module is not available adsisearcher can help.
(([adsisearcher]"samaccountname=ME988789").FindAll() | select -ExpandProperty properties).memberof | sortGetting all Users currently logged in to a machine/server
$ gwmi Win32_LoggedOnUser | select Antecedent
query usersAdd-ADGRoupMember
To add a user to an Active Directory Group user as in the Microsoft Docs
Add-ADGroupMember -Identity anygroup -Members anyuserCopy 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 $BSessionGet all commands from Module
(Get-Module (get-command -name <cmdlet>).source).ExportedCommandsThis 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 8080The 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 TCPNotes:
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)
}
}
$SourceNamesThe [void] prevents $SourceNames from containing the index numbers of its content.
PSReadline
Using PSReadline for better (bash-like) history. Docs
Last updated