Skip to main content
SysAdmin Shell Scripting Essentials

PowerShell Wait: Start-Sleep, Wait-Process, Start-Process -Wait

powershell wait refers to suspending or pausing script execution using Start-Sleep for time-based delays or Wait-Process to wait for a process to exit.

Start-Sleep -Seconds 5

Use Start-Sleep for unconditional delays and Wait-Process to block until a process exits. For launching external programs and waiting for completion, Start-Process -Wait is the canonical method.

Syntax

Start-Sleep [-Seconds] <int>
Start-Sleep [-Milliseconds] <int>
Start-Sleep [-Duration] <timespan>

Wait-Process [-Name] <string[]> [-Timeout <int>]
Wait-Process -Id <int[]> [-Timeout <int>]

Start-Process -FilePath <string> -Wait [-PassThru]

Options and Flags

Flag Type Default Description
-Seconds Int32 N/A (parameter set) Pause duration in seconds. Accepts fractional values since PowerShell 6.2.0.
-Milliseconds Int32 N/A (parameter set) Pause duration in milliseconds. Cannot be combined with -Seconds or -Duration.
-Duration TimeSpan N/A (parameter set) Pause duration as a TimeSpan object. Added in PowerShell 7.3.
-Name String[] N/A (mandatory) Process name(s) to wait for (Wait-Process). Wildcards not supported.
-Id Int32[] N/A (mandatory) Process ID(s) to wait for (Wait-Process).
-Timeout Int32 None (infinite) Max seconds to wait for process to exit (Wait-Process). Throws error if expired.
-PassThru Switch False Returns the process object (Start-Process -Wait -PassThru).
See also  Rename File In Linux: CLI Command Reference, Syntax, Flags

Usage Examples

Example 1: Pause script execution for 1.5 seconds

Start-Sleep -Seconds 1.5
Write-Output "Resuming after 1.5 seconds"

Fractional seconds supported since PowerShell 6.2.0. Use -Milliseconds 1500 for earlier versions.

Example 2: Wait for a process by name with timeout

Wait-Process -Name "notepad" -Timeout 30
if ($?) {
    Write-Output "Notepad closed within 30 seconds"
} else {
    Write-Output "Timeout reached or process not found"
}

$? indicates success. The cmdlet throws a non-terminating error if timeout expires or the process doesn’t exist.

Example 3: Start a process and wait for it to complete

$proc = Start-Process -FilePath "msiexec.exe" -ArgumentList "/i setup.msi /quiet" -Wait -PassThru
Write-Output "Installation exit code: $($proc.ExitCode)"

The -Wait parameter suspends the script until the process exits; -PassThru returns the process object to inspect the exit code.

Troubleshooting & Common Errors

Error/Issue Root Cause Resolution Command
Parameter set cannot be resolved using the specified named parameters Mixing -Seconds and -Duration Use only one parameter: Start-Sleep -Seconds 5
Cannot find process with name 'xyz' Process name is misspelled or not running Use Get-Process -Name 'xyz' to verify; use -Id instead
Start-Sleep : Cannot process argument Negative or non-numeric duration Ensure value is positive: $time = [Math]::Max(1, $time); Start-Sleep -Seconds $time
Wait-Process -Timeout not working Timeout parameter ignored in some versions Wrap in a do { Start-Sleep 1 } while ($proc.HasExited -eq $false -and $elapsed -lt $timeout) loop

Cross-Platform Equivalents

Operation PowerShell bash (Linux/macOS) cmd.exe
Time delay Start-Sleep -Seconds 5 sleep 5 timeout /t 5 /nobreak
Wait for process (name) Wait-Process -Name notepad while pgrep notepad; do sleep 1; done tasklist | findstr /i notepad (polling loop)
Wait for process (PID) Wait-Process -Id 1234 wait 1234 (only child process) No direct equivalent; use waitfor
Start and wait for GUI app Start-Process notepad.exe -Wait notepad; echo "done" (blocks terminal) start /wait notepad.exe

Exit Codes

PowerShell cmdlets do not return Unix-style exit codes. Success is indicated by no error output and $? being $true. The following table covers common error conditions.

See also  How To Check Printer's IP Address — Complete CLI Reference
Condition Meaning Operational Impact
Cmdlet runs without error Pause/wait completed successfully Script continues normally
Non-terminating error (e.g., process not found) Wait could not be fulfilled $? is $false; script continues unless $ErrorActionPreference = 'Stop'
Timeout expired (Wait-Process -Timeout) Process still running after specified seconds Throws error: “The process … did not finish before the timeout.”
Invalid parameter combination Parameter set resolution failure Terminating error; script stops

Performance Considerations

Selecting the right cmdlet and granularity minimizes idle CPU cycles. Use Start-Sleep -Milliseconds for sub-second pauses instead of -Seconds to avoid unnecessary delay. For process-level waiting, combine Start-Process -PassThru with Wait-Process -Id to eliminate polling overhead. Once you have the process object, Wait-Process -Id avoids repeated name resolution.

  • Granularity: Use -Milliseconds (e.g., 25 ms) rather than -Seconds to match actual idle requirements.
  • Process identification: Capture the process via Start-Process -PassThru then use Wait-Process -Id to avoid repeated name lookups.
  • Batch waiting: Supply multiple process IDs to Wait-Process -Id in a single call (e.g., Wait-Process -Id $pid1,$pid2) to wait on several processes concurrently.
  • Blocking vs. non-blocking: Start-Process -Wait blocks the current thread; for parallel workloads consider Start-Job or ForEach-Object -Parallel (outside this command set).
# Fine-grained wait using milliseconds
Start-Sleep -Milliseconds 25

# Wait for a specific process by ID for precise control
$proc = Start-Process -FilePath "notepad.exe" -PassThru
Wait-Process -Id $proc.Id
Write-Output "Process $($proc.Id) finished."

Frequently Asked Questions

What is the difference between Start-Sleep and Wait-Process?

Answer: Start-Sleep blocks the current thread for a specified duration; Wait-Process pauses until a named process exits or reaches a state.

Use Start-Sleep for unconditional time delays, e.g., throttling. Wait-Process monitors process status (running, stopped). Example:

Start-Sleep -Seconds 5
Wait-Process -Name "notepad" -Timeout 30

How do I fix “Wait-Job : The command cannot be run because the job has not completed” error?

Answer: Use Receive-Job -Wait instead of Wait-Job; or ensure you are waiting on a job object that has been started, not already received.

This error occurs when you call Wait-Job on a job that has already been fully consumed. Correct approach:

$job = Start-Job -ScriptBlock { ... }
$result = Receive-Job -Job $job -Wait -AutoRemoveJob

Does Wait-Process work on non-Windows platforms like Linux or macOS in PowerShell 7?

Answer: Yes, Wait-Process works cross-platform in PowerShell 7 on Linux and macOS, relying on the operating system’s process monitoring APIs.

It functions identically on all supported platforms. Example on Linux:

Wait-Process -Name "sleep" -Timeout 10

Note: Start-Sleep also works universally.

What is the fastest way to wait for multiple background jobs in PowerShell?

Answer: Use Wait-Job -Any to resume as soon as the first job completes, then process results iteratively, avoiding blocking on all jobs.

For parallel execution with minimal wait overhead, combine ForEach-Object -Parallel with Receive-Job -Wait. Example:

$jobs = 1..10 | ForEach-Object -Parallel { 
    Start-Job { param($id) Start-Sleep (Get-Random -Max 10); $id } -ArgumentList $_
}
while ($jobs) { 
    $done = Wait-Job -Job $jobs -Any 
    $done | Receive-Job -AutoRemoveJob
    $jobs = $jobs | Where-Object { $_.Id -ne $done.Id }
}