PowerShell Start-Process: Launch Apps and Scripts

PowerShell Start-Process: Launch Apps and Scripts

PowerShell Tips Editor 3 min read
PowerShell Start-Process: Launch Apps and Scripts

Deployment scripts don’t just run PowerShell commands — they launch installers, open external tools, run batch files, and wait for each step to complete before moving to the next. PowerShell Start-Process handles all of this: launching any executable, passing arguments, running elevated, waiting for completion, and capturing exit codes. This guide covers every practical pattern used in real automation scripts.

Quick Answer / TL;DR

# Launch an application and wait for it to finish
Start-Process -FilePath 'notepad.exe' -Wait

# Run a script elevated
Start-Process powershell -Verb RunAs -ArgumentList '-File C:\Scripts\setup.ps1'

Basic Start-Process Syntax

Launch any executable with Start-Process:

# Open a file (uses associated application)
Start-Process -FilePath 'C:\Reports\report.xlsx'

# Launch an application
Start-Process -FilePath 'notepad.exe'

# Launch with a full path
Start-Process -FilePath 'C:\Program Files\Tool\tool.exe'

# Open a URL in the default browser
Start-Process 'https://docs.microsoft.com/powershell'

# Open a folder in File Explorer
Start-Process -FilePath 'explorer.exe' -ArgumentList 'C:\Logs'

Without extra parameters, the process launches independently — Start-Process returns immediately and doesn’t wait. The new process runs in the background while your script continues.

Passing Arguments to the Process

Use -ArgumentList to pass command-line arguments:

# Pass arguments as a string
Start-Process -FilePath 'robocopy.exe' -ArgumentList 'C:\Source C:\Dest /E /LOG:C:\Logs\copy.log'

# Pass arguments as an array (safer for paths with spaces)
Start-Process -FilePath 'msiexec.exe' -ArgumentList @(
    '/i',
    'C:\Installers\MyApp.msi',
    '/quiet',
    '/log',
    'C:\Logs\install.log'
)

# Run a PowerShell script with arguments
Start-Process powershell -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass',
    '-File', 'C:\Scripts\deploy.ps1', '-Environment', 'Production'
# Process launches asynchronously
# Check Logs for results after -Wait

Passing arguments as an array is safer when paths contain spaces — each array element is passed as a separate argument token, which avoids quoting issues that occur with a single string.

Wait for Process to Finish with -Wait

Add -Wait to block the script until the launched process exits:

# Run installer and wait for completion before continuing
Write-Output 'Starting installation...'
Start-Process -FilePath 'msiexec.exe' -ArgumentList '/i "C:\Installers\App.msi" /quiet' -Wait
Write-Output 'Installation complete.'

# Run a batch file and wait
Start-Process -FilePath 'cmd.exe' -ArgumentList '/c C:\Scripts\build.bat' -Wait
Write-Output 'Build finished.'

# Run another PowerShell script and wait
Start-Process -FilePath 'powershell.exe' -ArgumentList '-File "C:\Scripts\step2.ps1"' -Wait
Starting installation...
Installation complete.
Build finished.

Run as Administrator with -Verb RunAs

The -Verb RunAs flag elevates the process through UAC:

# Relaunch as Administrator
Start-Process powershell -Verb RunAs

# Run a script elevated
Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile -File "C:\Scripts\install.ps1"'

# Run a specific tool elevated
Start-Process -FilePath 'regedit.exe' -Verb RunAs

The -Verb RunAs triggers the UAC prompt. This only works in an interactive desktop session with a GUI. In non-interactive contexts (scheduled tasks, CI/CD agents), configure the process to run as an account with the required permissions rather than using UAC elevation.

Capture Exit Code

To capture an exit code, use -Wait and -PassThru:

# Capture exit code from a process
$proc = Start-Process -FilePath 'robocopy.exe' `
    -ArgumentList 'C:\Source C:\Dest /E' `
    -Wait -PassThru -NoNewWindow

$exitCode = $proc.ExitCode
Write-Output "Robocopy exit code: $exitCode"

# Robocopy exit codes: 0=no change, 1=copied ok, 2=extra files, 8+=errors
if ($exitCode -ge 8) {
    Write-Error "Robocopy failed with exit code $exitCode"
}

# Generic success/failure check
$proc = Start-Process 'myapp.exe' -Wait -PassThru
if ($proc.ExitCode -ne 0) {
    throw "Process failed with exit code: $($proc.ExitCode)"
}
Robocopy exit code: 1

Exit code is only available after using -Wait. Without -Wait, the ExitCode property is $null because the process hasn’t finished yet.

Run Minimized or Hidden

Control the window style for background processes:

# Run hidden (no window)
Start-Process -FilePath 'cmd.exe' -ArgumentList '/c dir C:\ > C:\Temp\dirlist.txt' -WindowStyle Hidden

# Run minimized
Start-Process -FilePath 'notepad.exe' -WindowStyle Minimized

# Run without creating a new window (for console apps)
Start-Process -FilePath 'ping.exe' -ArgumentList 'google.com -n 4' -NoNewWindow -Wait

Common Errors and Fixes

  • Arguments with spaces need quoting inside -ArgumentList: When passing a path with spaces as a single string argument, wrap it in escaped quotes: -ArgumentList '/i \"C:\Program Files\App\setup.msi\"'. Using an array argument list is cleaner: @('/i', 'C:\Program Files\App\setup.msi').
  • Exit code only available after -Wait: Checking $proc.ExitCode without -Wait returns $null because the process is still running. Always pair -PassThru with -Wait when you need exit codes.

Related Cmdlets / See Also

Wrapping Up

Start-Process is the controlled way to launch external tools from PowerShell. Use -Wait to sequence steps, -PassThru to capture exit codes, -Verb RunAs for elevation, and -WindowStyle Hidden for background processes. Pass complex arguments as arrays to handle spaces correctly. Your next step: wrap your most common installer or external tool invocation in a Start-Process call with exit code checking.

Send-Item -To