Skip to main content

How to Get the Exit Code of a Background Process in a Batch Script

A common requirement in advanced scripting is to launch a time-consuming task in the background, allow the main script to continue with other work, and then, later, retrieve the result (the exit code) of that background process. The standard START command is perfect for launching background processes, but it introduces a major challenge: it detaches the new process, so the main script cannot simply check %ERRORLEVEL% to get its result.

This guide will teach you the standard and most robust asynchronous pattern for solving this problem: using a "wrapper" batch script and a temporary result file. You will learn how the main script can launch a task, proceed with its work, and then reliably retrieve the final exit code once the background task is complete.

The Core Challenge: START and Asynchronous Execution

When you use the START command, it launches a new program and your main script immediately continues to the next line without waiting. This is called asynchronous execution.

Example of the problem:

@ECHO OFF
ECHO Starting a background task that will take 5 seconds...
REM PING with a bad address will take time and return an ERRORLEVEL of 1
START "My Task" PING -n 1 non-existent-host.com

ECHO The START command has finished.
ECHO The ERRORLEVEL in the main script is: %ERRORLEVEL%

Output:

Starting a background task that will take 5 seconds...
The START command has finished.
The ERRORLEVEL in the main script is: 0
note

The %ERRORLEVEL% is 0 because the START command itself completed successfully. It says nothing about the PING command, which is still running (and will eventually fail) in its own separate process.

The Solution: A Wrapper Script with a Result File

The most reliable way to solve this is with a two-script system that communicates using a temporary file.

  1. Main.bat (The Controller): This is your primary script. Its job is to launch the background task and then, later, check for the result. Instead of launching the task directly, it launches a small "wrapper" script.
  2. Wrapper.bat (The Worker): This script's only purpose is to run the actual long-running task synchronously (without START). When the task finishes, the wrapper script immediately captures the %ERRORLEVEL%.
  3. The Result File (.tmp): The wrapper script's final action is to ECHO the captured exit code into a temporary file with a unique name. The existence of this file signals that the task is complete, and its content is the result.

The Scripts: Main.bat and Wrapper.bat

This is the main script:

Main.bat
@ECHO OFF
SETLOCAL
SET "TaskID=%RANDOM%"
SET "ResultFile=%TEMP%\result_%TaskID%.tmp"

ECHO --- Main Script ---
ECHO Launching background task with ID %TaskID%...
START "My Background Task" Wrapper.bat %TaskID%

ECHO Main script is now continuing with other work...
REM (Simulate other tasks)
TIMEOUT /T 5 > NUL

ECHO Now, waiting for the background task to complete...
:WaitForFile
IF EXIST "%ResultFile%" GOTO :FileFound
TIMEOUT /T 2 /NOBREAK > NUL
GOTO :WaitForFile

:FileFound
SET /P "ExitCode=" < "%ResultFile%"
DEL "%ResultFile%"

ECHO The background task finished with exit code: %ExitCode%
ENDLOCAL

and this is the wrapper script:

Wrapper.bat
@ECHO OFF
SET "TaskID=%1"
SET "ResultFile=%TEMP%\result_%TaskID%.tmp"

REM --- Run the actual long-running command here ---
REM This PING command will fail and set ERRORLEVEL to 1.
PING -n 1 non-existent-host.com > NUL 2> NUL

REM --- Immediately capture the exit code and write it to the result file ---
ECHO %ERRORLEVEL% > "%ResultFile%"
EXIT /B

How the Asynchronous Pattern Works

  1. Main.bat generates a unique ID and launches Wrapper.bat with that ID using START. Main.bat is now free to do other things.
  2. Wrapper.bat starts and executes the long-running PING command. It waits for the PING command to finish.
  3. When PING finishes, it sets the %ERRORLEVEL% for the Wrapper.bat script's environment.
  4. Wrapper.bat immediately runs ECHO %ERRORLEVEL% > result_12345.tmp, saving the result. It then exits.
  5. Meanwhile, Main.bat has finished its other work and is now in a loop, polling to see if result_12345.tmp exists.
  6. Once the file appears, Main.bat breaks the loop, reads the content of the file (1) into its ExitCode variable, deletes the temporary file, and reports the result.

A Simpler (but Flawed) Alternative: Waiting with TASKLIST

You can use a TASKLIST loop to wait for a process to disappear.

START "My App" my_app.exe
:WaitLoop
TASKLIST | FIND /I "my_app.exe" > NUL
IF %ERRORLEVEL% EQU 0 (
ECHO Process is still running. Waiting...
TIMEOUT /T 5 > NUL
GOTO :WaitLoop
)
ECHO Process has finished.

The Critical Flaw: This method can only tell you when the process has finished. It cannot tell you how it finished (i.e., you cannot get its exit code). For that, the wrapper script method is the only reliable solution.

Common Pitfalls and How to Solve Them

  • Race Conditions: If you run Main.bat multiple times in quick succession, they might generate the same %RANDOM% ID. Solution: For critical applications, use a more unique identifier like a GUID.
  • Cleanup: The main script is responsible for deleting the temporary result file. If the main script is terminated before the background task finishes, the temp file might be left behind. Solution: A cleanup script that periodically deletes old result_*.tmp files from the %TEMP% directory is a good practice.

Practical Example: Launching and Collecting Multiple Background Jobs

This script launches three "jobs" at once, each with its own wrapper and result file. It then waits for all three to complete before showing a final report.

This is the main script:

MultiJob.bat
@ECHO OFF
SETLOCAL
ECHO --- Launching 3 background jobs ---

START "Job 1" Wrapper.bat 1 "8.8.8.8"
START "Job 2" Wrapper.bat 2 "non-existent-host"
START "Job 3" Wrapper.bat 3 "1.1.1.1"

ECHO All jobs launched. Now waiting for completion...
FOR %%i IN (1 2 3) DO (
:Wait_%%i
IF EXIST "%TEMP%\result_%%i.tmp" (
SET /P "ExitCode_%%i=" < "%TEMP%\result_%%i.tmp"
DEL "%TEMP%\result_%%i.tmp"
) ELSE (
TIMEOUT /T 1 /NOBREAK > NUL
GOTO :Wait_%%i
)
)

ECHO.
ECHO --- All Jobs Complete. Results: ---
ECHO Job 1 Exit Code: %ExitCode_1%
ECHO Job 2 Exit Code: %ExitCode_2%
ECHO Job 3 Exit Code: %ExitCode_3%
ENDLOCAL
note

This requires a Wrapper.bat that accepts a second argument, like PING %2.

Conclusion

Getting the exit code from a background process is an advanced but powerful technique for creating parallel and asynchronous batch scripts.

  • The "Wrapper Script" and "Result File" pattern is the standard and most reliable method.
  • The main script uses START to launch a wrapper, which runs the task synchronously.
  • The wrapper captures %ERRORLEVEL% and writes it to a uniquely named file.
  • The main script polls for the existence of the result file to know when the task is complete and then reads its content to get the exit code.