When automating software installations through batch scripts, many developers encounter this frustrating behavior: msiexec.exe returns immediately after launching the installation, while the actual installation process continues running in the background. This becomes problematic when you need to chain installations or perform post-install tasks.
msiexec /i "python-3.11.4-amd64.msi" /quiet
REM Execution continues immediately here
Here are three robust methods to handle this scenario in your batch scripts:
Method 1: Using START /WAIT
The simplest approach is wrapping msiexec with START /WAIT:
START /WAIT msiexec /i "python-3.11.4-amd64.msi" /quiet
echo Python installation completed
Method 2: Checking Running Processes
For more control, check for msiexec processes:
msiexec /i "python-3.11.4-amd64.msi" /quiet
:check_process
tasklist /FI "IMAGENAME eq msiexec.exe" 2>NUL | find /I "msiexec.exe" >NUL
if %ERRORLEVEL% == 0 (
timeout /t 5 >NUL
goto check_process
)
echo Installation finished
Method 3: Using Windows Installer API (Advanced)
For complex scenarios, consider PowerShell integration:
@echo off
powershell -command "$installer = New-Object -ComObject WindowsInstaller.Installer; $installer.InstallProduct('python-3.11.4-amd64.msi', 'ACTION=INSTALL ALLUSERS=1')"
echo Python installed successfully
When chaining multiple MSI installations, proper synchronization becomes crucial:
@echo off
call :install_msi "prerequisite.msi"
call :install_msi "python-3.11.4-amd64.msi"
call :install_msi "dependency.msi"
goto :eof
:install_msi
START /WAIT msiexec /i "%~1" /quiet
exit /b
Always include proper error handling in production scripts:
@echo off
set MSI_LOG=%TEMP%\install_python.log
START /WAIT msiexec /i "python-3.11.4-amd64.msi" /quiet /L*V "%MSI_LOG%"
if %ERRORLEVEL% neq 0 (
echo Installation failed with error %ERRORLEVEL%
type "%MSI_LOG%"
exit /b %ERRORLEVEL%
)
echo Installation succeeded
When automating installations via batch scripts, many developers encounter the same frustration: msiexec
returns immediately while the actual installation continues in the background. This becomes problematic when you need to chain installations where subsequent steps depend on the completion of the MSI package.
The Windows Installer service (msiexec.exe
) operates asynchronously by design. When you execute:
msiexec /i package.msi /quiet /qn
The command returns immediately after spawning the installation process, not when installation completes.
Here are three robust approaches to detect MSI installation completion:
Method 1: Process Monitoring
@echo off
start /wait msiexec /i "Python-3.9.0.msi" /quiet /qn
:check_process
tasklist /FI "IMAGENAME eq msiexec.exe" 2>NUL | find /I "msiexec.exe" >NUL
if "%ERRORLEVEL%"=="0" (
timeout /t 5 >NUL
goto check_process
)
echo MSI installation completed
Method 2: Using MSI Transform with Logging
@echo off
set LOGFILE=%TEMP%\install_log.txt
msiexec /i "package.msi" /quiet /qn /L*V "%LOGFILE%"
:check_log
find /I "Installation completed successfully" "%LOGFILE%" >NUL
if ERRORLEVEL 1 (
timeout /t 5 >NUL
goto check_log
)
echo Installation verified via log
Method 3: Registry Check (When Applicable)
@echo off
msiexec /i "package.msi" /quiet /qn
:check_reg
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\{GUID}" >nul 2>&1
if %ERRORLEVEL% neq 0 (
timeout /t 5 >NUL
goto check_reg
)
echo Product found in registry - install complete
For more robust handling, combine batch with PowerShell:
@echo off
set INSTALL_CMD=msiexec /i "package.msi" /quiet /qn
set PSEXEC=powershell -NoProfile -ExecutionPolicy Bypass -Command
%PSEXEC% "$process = Start-Process -FilePath 'msiexec' -ArgumentList '/i','package.msi','/quiet','/qn' -PassThru; $process.WaitForExit()"
echo Installation completed successfully
- Not accounting for UAC prompts in non-silent modes
- Assuming all MSI packages use the same success codes
- Not handling rollback scenarios in your wait logic
- Forgetting about 64-bit vs 32-bit registry locations
Here's a complete batch script for Python installation with dependency checking:
@echo off
:: Install Python
echo Installing Python...
start /wait msiexec /i "python-3.10.0-amd64.msi" /quiet /qn ALLUSERS=1
:: Wait for installation
:check_python
python --version >nul 2>&1
if %ERRORLEVEL% neq 0 (
echo Waiting for Python installation to complete...
timeout /t 10 >nul
goto check_python
)
:: Proceed with pip installations
echo Installing required packages...
python -m pip install numpy pandas
Always validate your wait logic with:
- Fast installations (small MSI packages)
- Slow installations (large packages)
- Failed installations (simulate by canceling)
- Repair operations