When deploying applications through SCCM 2012 using PowerShell scripts as installers, administrators frequently encounter a frustrating scenario: while the script executes successfully and installs the target software, SCCM consistently reports a return code of 0 in the AppEnforce.log, regardless of the actual exit status the PowerShell script attempts to communicate.
Common PowerShell output methods like Write-Host
, Write-Output
, or simply returning a value don't properly communicate with SCCM because:
- PowerShell's output streams aren't the same as process exit codes
- SCCM's script interpreter looks specifically at the process termination status
- The PowerShell host process itself returns 0 unless explicitly terminated
To make SCCM correctly detect your script's status, you need to explicitly set the process exit code. Here's the definitive approach:
# Sample PowerShell installation script with proper exit code handling
try {
# Your installation logic here
$installResult = Start-Process -FilePath "setup.exe" -ArgumentList "/silent" -Wait -PassThru
if ($installResult.ExitCode -eq 0) {
# Success case
[Environment]::Exit(0)
}
elseif ($installResult.ExitCode -eq 3010) {
# Soft reboot required
[Environment]::Exit(3010)
}
else {
# Failure case
Write-Error "Installation failed with code $($installResult.ExitCode)"
[Environment]::Exit($installResult.ExitCode)
}
}
catch {
Write-Error $_.Exception.Message
[Environment]::Exit(1)
}
Several critical aspects ensure this works with SCCM:
- Use
[Environment]::Exit()
instead of return statements - Always wrap installation logic in try/catch blocks
- Preserve the original installer's exit codes when possible
- Document all expected return codes in your SCCM application
For installations requiring reboots (common exit code 3010), enhance your script with proper detection:
$rebootCodes = @(3010, 1641, 3011)
if ($rebootCodes -contains $installResult.ExitCode) {
# Set pending file rename operations flag if needed
if (Test-Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager") {
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "PendingFileRenameOperations" -Value $null
}
[Environment]::Exit(3010)
}
After implementation, check these log locations to verify proper exit code handling:
C:\Windows\CCM\Logs\AppEnforce.log
- Look for "Installation completed with exit code"C:\Windows\CCM\Logs\execmgr.log
- Check "Process completed with exit code" entries
If exit codes still aren't detected:
- Ensure your deployment type uses "PowerShell" as the script host
- Verify the account running the script has proper permissions
- Check for uncaught exceptions in PowerShell transcript logs
- Test with simple scripts first to isolate the issue
When deploying applications through SCCM 2012 using PowerShell scripts, many administrators encounter a frustrating scenario where SCCM consistently reports exit code 0 (success) regardless of the actual script execution outcome. This occurs because SCCM isn't properly capturing the exit codes PowerShell intends to communicate.
The issue stems from how SCCM interacts with PowerShell's execution host. By default, PowerShell exits with code 0 unless explicitly told otherwise, and SCCM doesn't properly parse Write-Host, Write-Output, or Return statements for deployment status.
Here are three reliable methods to ensure SCCM correctly interprets your PowerShell script's exit status:
# Method 1: Explicit exit code
try {
# Installation logic
Start-Process -FilePath "setup.exe" -ArgumentList "/silent" -Wait
exit 0 # Success
}
catch {
exit 1 # Generic failure
}
# Method 2: Using $LASTEXITCODE
& "setup.exe" /silent
exit $LASTEXITCODE
# Method 3: Custom error levels
$installResult = & "setup.exe" /silent
if ($installResult -eq 3010) {
exit 3010 # Reboot required
} else {
exit $installResult
}
1. Always use explicit exit codes rather than relying on implicit returns
2. Document your exit codes in the script header
3. Test with simple scripts first to validate SCCM interpretation
4. Consider wrapping your installation in a try-catch block
To troubleshoot exit code problems:
- Check SCCM's AppEnforce.log for detailed execution records
- Add verbose logging to your PowerShell script:
Start-Transcript -Path "C:\Logs\Install.log"
# Your installation code here
Stop-Transcript
For applications requiring reboots (exit code 3010), use this pattern:
$exitCode = (Start-Process -FilePath "setup.exe" -ArgumentList "/silent" -Wait -PassThru).ExitCode
if ($exitCode -eq 3010) {
# Set custom registry value for post-reboot continuation
New-ItemProperty -Path "HKLM:\SOFTWARE\YourApp" -Name "PendingReboot" -Value 1 -Force
}
exit $exitCode