By default, when a program (process) or external command is launched from a PowerShell script, the PowerShell interpreter continues executing the next commands without waiting for the process to complete. This can be inconvenient if you are running a program or command that takes a long time to complete or collect data. In this article, we will look at how to wait for the previous command to complete before moving to the next in a PowerShell script.
How PowerShell Executes Commands
Note that PowerShell behaves differently when launching native executables directly versus using Start-Process.
For example:
notepad.exe
It waits for Notepad to close.
The following command starts a separate process and immediately returns control to the script unless the -Wait parameter is used:
Start-Process notepad.exe

Ways to wait for a running command to complete in PowerShell
There are a number of ways that you can wait for a running command to complete in PowerShell:
- Start-Process with -Wait parameter
- Wait-Process
- Wait-Job
- Use pipelinechain operators && and || (available in PowerShell Core 7.x)
- Piping to Out-Null
Understanding Out-Null Behavior
Keep in mind that a common misconception is that piping a command to Out-Null causes PowerShell to wait for the process to finish. In reality, Out-Null only suppresses command output. Note that any waiting behavior comes from how PowerShell executes the command itself, not from Out-Null.
The other important thing to mention is that Out-Null does not provide a dedicated waiting mechanism. In most cases PowerShell already waits for native console apps to finish before continuing execution. Out-Null only suppresses command output. In this example, PowerShell starts the MSI package installation and waits for it to complete before proceeding to the next command:
& msiexec.exe /i "C:\Tools\appinstaller.msi" | Out-Null write-host 'next process'

In this example PowerShell waits because msiexec.exe is a synchronous process, not because of Out-Null itself.
Note. The Out-Null cmdlet is used when you don’t care about the output of an external command. To redirect the command output, you can use Out-File or Out-Host instead.
Wait using Start-Process cmdlet
To wait for a command to complete, you can use the Start-Process cmdlet with the -Wait parameter to run an external program. The following PowerShell code snippet opens a text file in Notepad. After the user closes the Notepad.exe process, the script will output the contents of the file to the console.
Start-Process notepad.exe -ArgumentList "C:\PS\ip_add.txt" -Wait Get-Content -path "C:\PS\ip_add.txt"

This method is useful when you need to ensure the installation process finishes before running post-installation tasks or wait for an external application to close before continuing the script.
Wait for a Process Object Using PassThru
In some automation tasks, you may need access to the process object itself instead of simply waiting for it to finish. In this case, you should use the -PassThru parameter with Start-Process.
The example below starts a process, stores the returned process object in a variable, and waits for it to exit:
$proc = Start-Process `
-FilePath "setup.exe" `
-ArgumentList "/silent" `
-PassThru
$proc.WaitForExit()
Note that unlike the -Wait parameter, this method gives you access to additional process information (including the process ID and exit code).
For example:
$proc = Start-Process `
-FilePath "setup.exe" `
-ArgumentList "/silent" `
-PassThru
$proc.WaitForExit()
Write-Host "Exit code:" $proc.ExitCode
Method described above is commonly used in deployment, software installation, and automation scripts where you need to check if a process completed successfully before continuing.
A common automation pattern is to validate the process exit code:
$proc = Start-Process `
-FilePath "setup.exe" `
-ArgumentList "/silent" `
-PassThru
$proc.WaitForExit()
if ($proc.ExitCode -ne 0)
{
throw "Installation failed with exit code $($proc.ExitCode)"
}
Tip. You can use -Wait when you only need to pause script execution. You should use -PassThru and WaitForExit() in case you also need to inspect the process properties/validate its exit code.
Wait using Wait-Process cmdlet
Using the Wait-Process cmdlet is another option. This cmdlet waits for a specified process to close before it allows the PowerShell script to continue.
Specify the process by name or by PID:
Wait-Process -Name "notepad"
or the process ID (PID):
Wait-Process -Id 4152 Write-Output " The following command is executed after the process is terminated"
You can also specify a timeout value with the following command (it throws an error in case the process is still running after 60 seconds):
Wait-Process -Name "notepad" -Timeout 60
Note. Start-Process -Wait does not support a timeout parameter. To enforce a timeout, use -PassThru with WaitForExit(milliseconds):
$proc = Start-Process "setup.exe" -PassThru
if (-not $proc.WaitForExit(30000)) { # 30 seconds
$proc.Kill()
throw "Process timed out"
}
When you are using -Name, Wait-Process waits for all matching processes. In environments where multiple instances may exist, you should use a specific PID because it is often safer.
If you need to run a complex job that consists of multiple commands and wait for it to complete, you can use the Start-Job and Wait-Job cmdlets:
# Run a background job from a PowerShell script
$myJob = Start-Job -ScriptBlock {
Get-Service
} # Wait for the script block in the job to complete Wait-Job -Job $myJob # List the job's results after execution $myJobResults = Receive-Job -Job $myJob
Write-Host $myJobResults # Clean up Remove-Job -Job $myJob
By using jobs in a PowerShell script, you can run multiple background tasks in parallel and ensure they finish before proceeding with the next steps.
Waiting for Parallel Tasks in PowerShell 7
PowerShell 7 introduced the ForEach-Object -Parallel feature. It allows multiple tasks to run concurrently without creating traditional background jobs.
Below you will find an example which starts several parallel tasks and automatically waits for all of them to finish before returning the results:
1..5 | ForEach-Object -Parallel {
Start-Sleep -Seconds 5
"Task $_ completed"
} Here is an output:
Task 1 completed
Task 2 completed
Task 3 completed
Task 4 completed
Task 5 completed
Unlike Start-Job, PowerShell automatically waits for all parallel runspaces created by ForEach-Object -Parallel to complete before continuing execution. This method is usually simpler for processing multiple items concurrently in PowerShell 7 and later.
Note. The ForEach-Object -Parallel parameter is available only in PowerShell 7+. Keep in mind that it is not supported in Windows PowerShell 5.1.
In PowerShell Core 7.x, you can use the && and || operators to conditionally chain pipelines.
- && operator executes the right pipeline if the left pipeline was executed successfully (checked by result code)
- || operator will execute the right pipeline if the left pipeline fails
These conditional chain pipeline operators can be used when you need to run a specific command after the first command has successfully completed. For example:
msiexec.exe /i app.msi /qn &&
Copy-Item c:\tools\config.yaml $env:APPDATA\MyApp -Force
Which Waiting Method Should You Use?
| Method | Best Use Case | Supports Timeout | Returns Exit Code | Notes |
|---|---|---|---|---|
| Start-Process -Wait | External installers and applications | No | No | Waits for the process to exit before continuing |
| PassThru + WaitForExit() | Automation and deployment scripts | No | Yes | Provides access to the process exit code |
| Wait-Process | Existing process by PID or name | Yes | No | Can wait for running processes with an optional timeout |
| Wait-Job | Background PowerShell jobs | Yes | Job results | Used for PowerShell jobs created with Start-Job |
| ForEach-Object -Parallel | Parallel execution in PowerShell 7+ | N/A | Pipeline output | Designed for concurrent task execution |
| && / || | Conditional command chaining | N/A | Uses command success status | Runs commands based on success (&&) or failure (||) of the previous command |
Conclusion
The methods discussed in this article ensure that PowerShell waits for the specified process to complete before it proceeds to the next command. Waiting on actual process completion is more reliable than using Start-Sleep because script execution continues only after the target process, job, or task has actually finished.
What is the difference between -Wait and WaitForExit()?
-Wait simply pauses the script until the process finishes. WaitForExit() is used with Start-Process -PassThru and returns a process object, allowing you to inspect properties such as the process ID and exit code.
Does Out-Null make PowerShell wait for a command to finish?
No. Out-Null only suppresses command output. Any waiting behavior comes from how PowerShell executes the command itself, not from Out-Null.
When should I use Wait-Process instead of Start-Process -Wait?
Use Start-Process -Wait when launching a new application and waiting for it to exit. Use Wait-Process when the process is already running and you need to wait for a specific process name or PID.
Is Start-Sleep a good way to wait for a process?
Generally, no. Start-Sleep pauses execution for a fixed amount of time and does not verify whether a process has actually finished. Waiting on the actual process, job, or task is usually more reliable.
