pwsh / PowerShell: Run Scripts in Windows CI
pwsh is the cross-platform PowerShell Core executable; on Windows CI it runs script files or inline commands and reports success through its exit code.
GitHub Actions defaults to pwsh on Windows runners. Knowing how PowerShell maps native exit codes and thrown errors to job pass/fail is the difference between a green build and a silent failure.
What it does
pwsh launches PowerShell Core (7.x). It runs a script with -File, an inline command with -Command, and exits with $LASTEXITCODE from the last native program or 0/1 from PowerShell itself. Windows PowerShell 5.1 ships as powershell.exe; pwsh is the newer, separate executable.
Common usage
# run a script file (preferred in CI)
pwsh -NoProfile -File ./build.ps1 -Configuration Release
# run inline; -Command is the default in many shells
pwsh -NoProfile -Command "Get-ChildItem env: | Out-String"
# make any error fail the step
pwsh -Command "\$ErrorActionPreference='Stop'; ./deploy.ps1"Options
| Flag | What it does |
|---|---|
| -File <path> | Run a .ps1 script file; remaining args are passed to it |
| -Command <text> | Run an inline command or script block |
| -NoProfile | Skip loading profile scripts (faster, deterministic in CI) |
| -NoLogo | Suppress the copyright banner |
| -ExecutionPolicy <p> | Set the policy for this session, e.g. Bypass |
| -NonInteractive | Fail instead of prompting for input |
In CI
Always pass -NoProfile so a machine profile cannot change behavior between runs. Set $ErrorActionPreference = "Stop" at the top of CI scripts so a non-terminating error (like a failed cmdlet) actually stops the job instead of continuing.
Common errors in CI
A step shows green even though a command failed: PowerShell only fails the step on a terminating error or a non-zero $LASTEXITCODE, so a non-terminating cmdlet error is ignored unless $ErrorActionPreference="Stop". "The term 'pwsh' is not recognized" means PowerShell Core is not installed (use powershell for 5.1, or install pwsh). After calling a native exe, check $LASTEXITCODE explicitly; $? reflects only the last PowerShell operation.