Snippets - PowerShell
Basic Where
Get-WindowsOptionalFeature -Online | ?{ $_.State -Like 'Enabled'} | Select FeatureName
Admin check
Run Test-IsAdmin
to call the function and output true or false. I use this for logging. If you want a hard fail for lack of admin use #Requires -RunAsAdministrator
function Test-IsAdmin {
try {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal -ArgumentList $identity
return $principal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator )
} catch {
Throw "Failed to determine if the current user has elevated privileges. The error was: '{0}'." -f $_
}
}
Start service on remote machine
Get-Service -ComputerName <machine> -Name <service> | Set-Service -Status Running
Grep
<stdout> | findstr -i <term>
Select-String -Path * -Pattern ".*STRING.*" -ErrorAction SilentlyContinue
Connect to Sharepoint online
# the name appearing in the URL of your sharepoint site before sharepoint.com
$orgName=""
# connect without using get-credential so that the modern prompt is generated allowing 2FA
Connect-SPOService -Url https://$orgName-admin.sharepoint.com
Dates
$Date = Get-Date -Format yyyy-MM-dd
$Year = Get-Date -Format yyyy
$Month = Get-Date -Format MM
$Day = Get-Date -Format dd
$Hour = Get-Date -Format HH
$Minute = Get-Date -Format mm
$Second = Get-Date -Format ss
$Time = Get-Date -Format HH-mm-ss
$TimeStamp = Get-Date -Format s | foreach {$_ -replace ":", "-"}
Remove specific index from array
$array = 1,2,3
$newArray = $array | ? { $_ -ne $array[0] }
Remove empty objects from array
$array | Where-Object {$_}
Get Fonts
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
(New-Object System.Drawing.Text.InstalledFontCollection).Families
Check object for property
If (Get-Member -inputobject $OBJECT -name "PROPERTY" -Membertype Properties) { Write-Host 'yes' }
Counting
$i | measure -Line -Character -Word
Date manipulation
Get the date 6 months ago
$date = Get-Date
$date.AddMonths(-6)
Parameters
param (
[Parameter(Mandatory=$True)]
[Object]$smptTo,
[Parameter(Mandatory=$True)]
[Object]$messageSubject,
[Parameter(Mandatory=$True)]
[Object]$messageBody,
[Parameter(Mandatory=$False)]
[Object]$messageAttachment,
)
Replace
This uses regex
$a -replace "boring!$", "exciting!"
Replace in files
ForEach ($file in $(Get-ChildItem -Path "./*" -Recurse -Attributes !Directory)) {
$dirty = Get-Content $file
$dirty -Replace 'this', 'that' | Set-Content $file
}
Splitting
$string = "a powershell $([char]0x007B) string $([char]0x007D) contains stuff"
$string.Split("{,}")
With a pipe
$rawData0 -Split "-- S.M.A.R.T"
Timers
#Create a Stopwatch
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
#You can use the $stopWatch variable to see it
$stopWatch
#Go ahead and check out the methods and properties it has
$stopWatch | Get-Member
$stopwatch.Start()
$stopwatch.Elapsed
$stopwatch.Stop()
$stopwatch.Reset()
Try-Catch
try {
This is not allowed "This is Allowed"
} catch {
Write-Host "Error occured" -BackgroundColor DarkRed
}
Printing the error that caused the catch
Use Write-Host $_
Get word count from text files recursively
Get-ChildItem -Recurse | Select Name,@{Name='Count'; Expression={(Get-Content $_ | Measure-Object -Word).Words}}
Remove all lines after X from selection/text file
$txt = Get-Content file.txt
$to = '## Home'
$i = 0
Do { $txt[$i++] } Until ($txt[$i] -eq $to)
Simpler
$(Get-Content .\2021-09-27.md -Raw ) -replace '## Home[\s\S]+'
ForEach ($file in (Get-ChildItem -Recurse -Filter '20*.md')) {
$(Get-Content $file -Raw) -replace '## Home[\s\S]+' | Set-Content $file
}
Remove all work lines form daily notes
$(Get-Content .\2022-01-06.md -Raw) -replace '# Daily[\s\S]+## Home','# Daily'
ForEach ($file in (Get-ChildItem -Recurse -Filter '*.md')) {
$(Get-Content $file -Raw) -replace '# Daily[\s\S]+## Home','# Daily' | Set-Content $file
}
or
ForEach ($file in (Get-ChildItem -Recurse -Filter '20*.md')) {
$(Get-Content $file -Raw) -replace '## Home[\s\S]+' | Set-Content $file
}
Get Directory Size
(Get-ChildItem C:\Temp\ -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
(Get-ChildItem C:\Temp\ -Recurse | Measure-Object -Property Length -Sum).Sum / 1GB
Get directory size for every child directory
ForEach ($dir in $(Get-ChildItem -Directory)) {
Write-Host $dir.name -ForegroundColor green
(Get-Childitem $dir -Recurse | Measure-Object -Property Length -Sum).Sum / 1GB
}
Search for file names
Get-Childitem –Path C:\ -Include *Term* -File -Recurse -ErrorAction SilentlyContinue
Get-Childitem –Path C:\ -Include "*Term*" -Exclude "*.png","*.jpg" -File -Recurse -ErrorAction SilentlyContinue
File extensions function
[System.IO.Path]::ChangeExtension("Untitled.md",".new")
File exists
If (Test-Path $vsLayout) {
Write-Host "Layout exists" -ForegroundColor Green
}
Wait for file to exist
While (!(Test-Path $vsLayout)){
Write-Host "Waiting for layout creation..." -ForegroundColor Yellow
Start-Sleep -Seconds 3
}
Prepend string to items in array
$test = $jsonConfig.components.ForEach({"--add " + $_})
Get object type
$test.GetType()
Random String
add-type -AssemblyName System.Web
[System.Web.Security.Membership]::GeneratePassword(15,2)
Compare 2 directories
Quick way to get just names
$Folder1 = Get-childitem "C:\Folder1"
$Folder2 = Get-childitem "C:\Folder2"
$Compare-Object $Folder1 $Folder2 -Property Name
If you need to retain properties
$Folder1 = Get-childitem "C:\Folder1"
$Folder2 = Get-childitem "C:\Folder2"
$Difference = $Folder1 | Where {$Folder2.Name -notcontains $_.Name}
Pull differences into a new directory
Copy-Item $Difference.FullName -Destination .\Difference_Directory
If file exists
If (Test-Path C:\filename) {
Write-Warning "File exists"
}