From Legacy CLI to Object-Oriented Automation

The Windows shell environment has shifted fundamentally. The current standard is defined by three decoupled components: PowerShell 7+ as the shell, Windows Terminal as the host, and WinGet as the native package manager. For users re-entering the Windows ecosystem, understanding these boundaries is the prerequisite for everything else.

The Core Paradigm: Objects Over Strings

The defining difference between PowerShell and Unix-like shells is the pipeline. Bash passes text streams that require grep, sed, or awk for parsing. PowerShell passes .NET objects. Every cmdlet receives structured objects and emits structured objects — no string parsing required.

Four operations cover the majority of pipeline work:

  • Get-Member (alias gm) — inspect the properties and methods of any object in the pipeline
  • Where-Object (alias ?) — filter objects by logical checks on their properties
  • Select-Object (alias select) — extract specific properties or limit output count
  • Format-Table / Format-List — convert objects to display strings; use only as the final step in a pipeline, as they break further automation

The last point is a common source of pipeline failures. Formatting cmdlets are terminal — once an object becomes a display string, its properties are no longer accessible to downstream cmdlets.

Environment and Productivity Enhancements

Windows Terminal

The legacy conhost.exe host is deprecated. Windows Terminal provides GPU-accelerated text rendering, multiple tabs, and split panes.

Key shortcuts:

  • Alt + Shift + D — vertical split
  • Alt + Shift + - — horizontal split
  • Ctrl + Shift + F — search the buffer
PSReadLine

Modern PowerShell includes PSReadLine, which provides readline functionality comparable to Zsh or Fish.

Enable ghost-text completions from command history:

Set-PSReadLineOption -PredictionSource History

Key bindings:

  • Ctrl + Space — full menu-based completion
  • Ctrl + R — reverse history search (regex-compatible)
  • Alt + A — select the current line for editing
  • F12 — clear the screen while preserving the buffer
Profile Configuration

The environment is configured via $PROFILE. Open it directly with:

code $PROFILE

Use the profile to set aliases and import modules automatically on startup. Changes take effect in new sessions; use . $PROFILE to reload without restarting the terminal.

WinGet: Native Package Management

WinGet replaces the manual download-and-execute workflow for software installation and system state management.

# Install a package
winget install Git.Git

# Audit all installed software (including non-WinGet installs)
winget list

# Upgrade all outdated applications
winget upgrade --all

# Export current machine state to a declarative bundle
winget export -o bundles.json

# Replicate that state on a new node
winget import -i bundles.json

The export/import workflow is particularly useful for provisioning new workstations to a known software baseline without manual installation sequences.

Execution Contexts and Privilege Elevation

Windows security architecture defines three primary execution contexts. Understanding their boundaries is a prerequisite for writing scripts that behave correctly across deployment environments.

Standard User (Least Privilege)

The default execution context. Scripts here have limited access to the HKEY_LOCAL_MACHINE (HKLM) registry hive and system-protected directories (C:\Windows, C:\Program Files).

Use Resolve-Path to ensure scripts handle relative paths correctly within user profiles. Avoid hardcoding paths that assume a specific user directory structure.

Administrative User (Elevated)

Requires UAC consent. Provides write access to HKLM and system directories.

Spawn an elevated shell from a standard context:

Start-Process pwsh -Verb RunAs

Detect elevation state within a script:

([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
SYSTEM (S-1-5-18)

The highest privilege level, reserved for Windows Services and the kernel. SYSTEM has broader access than a local Administrator — including certain protected registry keys and hardware drivers — but lacks a user profile (HKCU).

Consequences for script authors:

  • Many environment variables available to users are absent in SYSTEM context
  • Network paths and UNC shares that rely on user credentials are inaccessible
  • Scripts deployed via Intune or SCCM run as SYSTEM and must use absolute paths and handle the absence of a desktop interaction layer

For debugging in SYSTEM context, use PsExec from the Sysinternals suite:

PsExec -s -i powershell.exe

Scripting Standards

Three settings should be present in any production PowerShell script:

Strict mode catches uninitialized variables and references to non-existent properties before they produce silent failures:

Set-StrictMode -Version Latest

ErrorAction Stop forces try/catch blocks to trigger on non-terminating errors, which PowerShell would otherwise silently continue past:

Get-Item $path -ErrorAction Stop

Modules over scripts — modern Windows development favors .psm1 module files over standalone scripts for better scoping, reusability, and dependency management. A script that grows beyond a single purpose should be refactored into a module.