To make PowerShell wait for a command to finish, start it with Start-Process -Wait. Add -PassThru as well, and you get the process object back, so you can read its exit code once it closes:
$process = Start-Process -FilePath cmd.exe -ArgumentList '/c', 'exit 3' -Wait -PassThru -NoNewWindow
"Exit code: $($process.ExitCode)"
Output:
Exit code: 3

Without -Wait, Start-Process hands control back right away while the program keeps running. I’ll show what -Wait really waits for, how Wait-Process differs, timeouts, the Out-Null trick, and the rest of Start-Process.
I ran each example in PowerShell 7.6 and Windows PowerShell 5.1, using console tools like cmd and ping so you can repeat the results.
Start a program with Start-Process
At its simplest, give Start-Process a file path. PowerShell starts the program and immediately moves to the next line:
Start-Process -FilePath notepad.exe
Start-Process -FilePath 'C:\Reports\Q3-sales.xlsx' # opens with the default app
A document opens in whatever app is registered for its file type, just like double-clicking it. If Windows can’t find a program, find where the executable lives and pass the full path.
| Parameter | What it does |
|---|---|
-FilePath | The program, script or document to start |
-ArgumentList | Arguments for the program, as one string or an array |
-Wait | Waits until the process and its child processes exit |
-PassThru | Returns a process object, for example to read ExitCode |
-NoNewWindow | Runs a console program in the current window |
-WindowStyle | Normal, Hidden, Minimized or Maximized |
-WorkingDirectory | The folder the process starts in |
-Verb RunAs | Starts the process elevated (as administrator) |
-Credential | Starts the process as another user |
How does Start-Process -Wait work?
By default, Start-Process launches the program asynchronously. -Wait changes that: PowerShell blocks until the program exits, and only then runs the next line.
The classic use is an installer that must finish before the next step. For example, a silent MSI install:
$install = Start-Process msiexec.exe -ArgumentList '/i "C:\Installers\Contoso Agent.msi" /qn' -Wait -PassThru
"Installer exit code: $($install.ExitCode)"
I didn’t run this one, since it would install software. The same pattern works when you uninstall a program with PowerShell and need to know it’s gone before you continue.
-Wait also waits for child processes
Here’s the detail most guides skip. -Wait waits for the whole process tree, so PowerShell keeps waiting for any child process the program started.
Wait-Process only watches the process you name. This test starts cmd, which launches ping in the background and quits at once:
$cmd = '/c', 'start "" /b ping -n 4 127.0.0.1 >nul'
$t = Measure-Command { Start-Process cmd.exe -ArgumentList $cmd -Wait -WindowStyle Hidden }
&qu