PowerShell Script Tips & Tricks
I think most of this is doubled up in other notes but fuck it we publish.
Patterns and techniques for making scripts more reusable and user-friendly.
Ask for input instead of hardcoding
Use Read-Host to prompt for a value at runtime — no more swapping emails in Notepad.
$mailbox = Read-Host "Enter mailbox"Or inline:
Get-Mailbox -Identity (Read-Host "Enter mailbox") | Select ArchiveQuotaAuto-connect to Exchange Online
Add this to the top of any EXO script. Connects only if not already connected.
if (-not (Get-ConnectionInformation)) {
Connect-ExchangeOnline
}Requires: ExchangeOnlineManagement module
Auto-connect to Microsoft Graph
Add this to the top of any Graph script. Connects only if not already connected.
if (-not (Get-MgContext)) {
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
}Requires: Microsoft.Graph.Identity.SignIns module
Check if installed:
Get-Module Microsoft.Graph.Identity.SignIns -ListAvailableInstall if missing:
Install-Module Microsoft.Graph.Identity.SignInsCheck if connected to MgGraph
Get-MgContextEnvironment Variables in Paths
PowerShell does not expand CMD-style environment variables like %USERPROFILE% inside strings. That syntax only works in Command Prompt and batch files.
In PowerShell, environment variables are accessed via $env:VARIABLENAME:
# Wrong — PowerShell treats this as a literal string
"$%USERPROFILE%\Desktop\file.csv"
# Right
"$env:USERPROFILE\Desktop\file.csv"Common ones:
| CMD | PowerShell |
|---|---|
%USERPROFILE% | $env:USERPROFILE |
%APPDATA% | $env:APPDATA |
%TEMP% | $env:TEMP |
%COMPUTERNAME% | $env:COMPUTERNAME |
%USERNAME% | $env:USERNAME |
Example — export CSV to desktop regardless of who’s logged in:
$results | Export-Csv -Path "$env:USERPROFILE\Desktop\LicensedUsers.csv" -NoTypeInformationThis works on any machine without hardcoding C:\Users\Rick\...
Write-Host — printing messages to the terminal
Use Write-Host to print status messages, section headers, or confirmations. It outputs directly to the terminal and doesn’t affect the pipeline.
# Basic message
Write-Host "Done."
# With a leading blank line for readability
Write-Host "`nDone."
# With a variable
Write-Host "`nExported to $env:USERPROFILE\Desktop\LicensedUsers.csv"The backtick ` is PowerShell’s escape character. `n is a newline — handy for spacing output between sections.
Force immediate output formatting
PowerShell sometimes buffers pipeline output and prints it out of order. Add | Format-Table to force it to print immediately.
Get-MailboxStatistics $mailbox -Archive | Select DisplayName, TotalItemSize, ItemCount | Format-TableComparison Operators
PowerShell can’t use >, <, >= etc. directly in conditionals — it uses text-based operators instead:
| Operator | Meaning |
|---|---|
-eq | Equal to |
-ne | Not equal to |
-gt | Greater than |
-ge | Greater than or equal to |
-lt | Less than |
-le | Less than or equal to |
if ($hour -ge 8 -and $hour -lt 18) { ... }Also useful for day-of-week checks — DayOfWeek returns the full day name as a string:
$day = (Get-Date).DayOfWeek
if ($day -ne 'Saturday' -and $day -ne 'Sunday') { ... }Scripts
checkarchive.ps1
Check archive size and quota for a mailbox.
if (-not (Get-ConnectionInformation)) {
Connect-ExchangeOnline
}
$mailbox = Read-Host "Enter mailbox"
Write-Host "`n--- Archive Stats ---"
Get-MailboxStatistics $mailbox -Archive | Select DisplayName, TotalItemSize, ItemCount | Format-Table
Write-Host "`n--- Archive Quota ---"
Get-Mailbox -Identity $mailbox | Select ArchiveQuota, ArchiveWarningQuota, AutoExpandingArchiveEnabled | Format-Tablenewtap.ps1
Generate a Temporary Access Pass for a user.
if (-not (Get-MgContext)) {
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
}
New-MgUserAuthenticationTemporaryAccessPassMethod -UserId (Read-Host "Enter UPN") -LifetimeInMinutes 60 | Select TemporaryAccessPassremovetaps.ps1
Remove all Temporary Access Passes for a user.
if (-not (Get-MgContext)) {
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
}
$upn = Read-Host "Enter UPN"
Get-MgUserAuthenticationTemporaryAccessPassMethod -UserId $upn | ForEach-Object {
Remove-MgUserAuthenticationTemporaryAccessPassMethod -UserId $upn -TemporaryAccessPassAuthenticationMethodId $_.Id
}setpasswordneverexpires.ps1
Set password never expires on all enabled local accounts. Safe to run as system — only affects local accounts, not Entra/domain accounts.
Get-LocalUser | Where-Object {$_.Enabled -eq $true} | Set-LocalUser -PasswordNeverExpires $trueNotes
- Scripts live at
C:\Users\Rick\Scripts— symlinked toOneDrive - Coytis\Scriptsso they sync across both PCs automatically - Always use
Read-Hostinstead of hardcoded emails/UPNs in scripts that will be reused or published in KBs - Connection checks mean scripts are safe to run standalone or after an existing session — no double auth prompts