Fix Intune Win32 App Timeout 0x87D300C9
Intune Win32 app error 0x87D300C9 usually appears when Company Portal or the Intune admin center reports this message:
The unmonitored process is in progress, however it may timeout. (0x87D300C9)
Do not start by rebuilding the .intunewin package. This error usually means the Intune Management Extension started your command, but the process it launched did not return control in the way Intune expects. In practice, that often comes from an installer that spawned another process, waited on user input, opened a child setup engine, wrote logs to a blocked path, or ran with switches that work interactively but not as SYSTEM.
Use this runbook when a Win32 app installs manually, but fails from Company Portal, required assignment, or ESP with 0x87D300C9.
Quick Fix checklist
Work in this order on one affected test device:
- Confirm the Intune failure is
0x87D300C9, not a detection-only failure such as0x87D1041C. - Copy the exact install command from the Win32 app properties in Intune.
- Test the command locally as
SYSTEM, not only from an elevated admin PowerShell prompt. - Make the installer fully silent. Remove any switch that can open a prompt, restart dialog, browser window, or licensing screen.
- If the installer spawns a child process, wrap it with a script that waits for the real setup process and exits with the final code.
- Set a sane Intune install behavior and install timeout. Do not hide a broken command by setting an extreme timeout.
- Write logs to
C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\VendorAppor another machine-wide path thatSYSTEMcan create. - Check
IntuneManagementExtension.log,AppWorkload.log, andAgentExecutor.logunderC:\ProgramData\Microsoft\IntuneManagementExtension\Logs. - Confirm the command exits with
0or a return code mapped in Intune, such as3010for soft reboot. - Sync the device, restart the Microsoft Intune Management Extension service if needed, then retry the assignment.
Root Cause
0x87D300C9 is a process monitoring problem during Win32 app enforcement. Intune calls the install command through the Intune Management Extension. The extension expects the command to run, finish, and return a code that can be interpreted against the app’s return-code table.
The failure usually falls into one of these buckets:
- The install command starts a bootstrapper and exits before the real installer finishes.
- The install command starts a bootstrapper that never exits because it is waiting on a child process.
- A supposedly silent installer is showing a hidden prompt in session 0.
- The command works as a signed-in admin but fails as
SYSTEM. - The installer writes logs or temp files to a user profile path that does not exist for
SYSTEM. - A wrapper script uses
Start-Processwithout-Waitor without passing the child process exit code back to Intune. - The app needs network content, proxy access, or a mapped drive that is not available to the Intune Management Extension.
- The install timeout is shorter than the real install time for that package on slow hardware.
Microsoft’s Win32 troubleshooting guidance points admins to the Intune Management Extension logs for app check-in, installs, applicability, detection, and PowerShell execution. Microsoft also documents that Win32 app processing includes detection, applicability, content download, install command execution, and post-install detection. 0x87D300C9 sits in the install execution part of that chain.
Logs and where to check
Start in the Intune admin center:
Intune admin center > Apps > Windows > select the Win32 app > Monitor > Device install status
Open the affected device record and confirm the status text includes 0x87D300C9 or the unmonitored process message.
On the Windows endpoint, collect these logs:
C:\ProgramData\Microsoft\IntuneManagementExtension\Logs
Focus on:
| Log file | What to look for |
|---|---|
IntuneManagementExtension.log | Policy check-in, app assignment, command execution flow, enforcement state |
AppWorkload.log | Win32 app install, applicability, detection, and reporting details |
AppActionProcessor.log | App action processing and detection/applicability checks |
AgentExecutor.log | PowerShell execution when install or requirement scripts are involved |
ClientHealth.log | Intune Management Extension health issues that can confuse app retries |
Use this PowerShell to pull the useful lines:
$LogRoot = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs'
$Terms = @(
'0x87D300C9',
'unmonitored process',
'timeout',
'install command',
'process',
'exit code',
'enforcement'
)
Get-ChildItem $LogRoot -Filter '*.log' |
Select-String -Pattern $Terms -SimpleMatch |
Select-Object Path, LineNumber, Line |
Format-List
Then search by app name or app ID:
$AppName = 'Contoso VPN Client'
Get-ChildItem 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs' -Filter '*.log' |
ForEach-Object {
Select-String -Path $_.FullName -Pattern $AppName -Context 8,12
}
A typical broken flow looks like this:
Install command line: setup.exe /silent
Process started.
Child installer launched.
Parent process is still running or no final exit code is returned.
The unmonitored process is in progress, however it may timeout.
That tells you the fix is the command wrapper, not the assignment group.
Test the install command as SYSTEM
An elevated admin console is not enough. Intune installs Win32 apps through the Intune Management Extension, which runs as SYSTEM for system-context apps. A command can pass as your admin account and fail for Intune because environment variables, certificates, network access, and profile paths are different.
Use PsExec from Microsoft Sysinternals on a test device:
# Run from an elevated PowerShell prompt after downloading PsExec.
.\PsExec.exe -i -s powershell.exe
In the new SYSTEM PowerShell window, move into the extracted test folder and run the exact Intune command:
whoami
Set-Location 'C:\Temp\ContosoApp'
.\install.cmd
$LASTEXITCODE
If the command hangs, opens a UI, waits for input, or returns a code Intune does not accept, you have reproduced the failure outside Intune.
Fix silent switch and child process problems
Many vendor installers are bootstrappers. setup.exe /quiet might start msiexec.exe, installshield.exe, update.exe, or another vendor process. If your wrapper exits too early, Intune can start detection while the real install is still running. If your wrapper never exits, Intune eventually reports timeout behavior.
Use a wrapper that waits and returns the real code. For an MSI, keep it simple:
$Msi = Join-Path $PSScriptRoot 'ContosoClient.msi'
$Log = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\ContosoClient-install.log'
$Process = Start-Process -FilePath 'msiexec.exe' `
-ArgumentList "/i `"$Msi`" /qn /norestart /L*v `"$Log`"" `
-Wait `
-PassThru
exit $Process.ExitCode
For an EXE bootstrapper, test the vendor’s documented silent switches and still wait for completion:
$Installer = Join-Path $PSScriptRoot 'ContosoSetup.exe'
$Log = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\ContosoClient-setup.log'
$Process = Start-Process -FilePath $Installer `
-ArgumentList "/quiet /norestart /log `"$Log`"" `
-Wait `
-PassThru
exit $Process.ExitCode
If the vendor bootstrapper exits before a child process finishes, wait for the child by name after launch. Keep the wait bounded so a broken installer cannot run forever:
$Installer = Join-Path $PSScriptRoot 'setup.exe'
$Process = Start-Process -FilePath $Installer -ArgumentList '/silent' -PassThru
$Process.WaitForExit()
$Deadline = (Get-Date).AddMinutes(20)
do {
$Child = Get-Process -Name 'ContosoSetup','msiexec' -ErrorAction SilentlyContinue
if (-not $Child) { break }
Start-Sleep -Seconds 5
} while ((Get-Date) -lt $Deadline)
if (Get-Process -Name 'ContosoSetup' -ErrorAction SilentlyContinue) {
Write-Error 'Contoso setup process did not finish before timeout.'
exit 1603
}
exit $Process.ExitCode
Do not use Start-Process without -Wait unless you have a deliberate reason and a follow-up wait. This is one of the most common causes of Intune app timing failures.
Fix log path and temp path issues
Avoid writing installer logs to the current user’s desktop, downloads folder, or %TEMP% when packaging for Intune. In system context, those paths are not the admin profile you tested with.
Use a machine-wide folder:
$LogDir = 'C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\ContosoClient'
New-Item -Path $LogDir -ItemType Directory -Force | Out-Null
$Log = Join-Path $LogDir 'install.log'
If the vendor installer insists on a temp folder, set one explicitly:
$TempDir = 'C:\ProgramData\ContosoClient\Temp'
New-Item -Path $TempDir -ItemType Directory -Force | Out-Null
$env:TEMP = $TempDir
$env:TMP = $TempDir
Then rerun the command as SYSTEM. If it only fails when the log path points to a user folder, the package was never safe for Intune deployment.
Check Intune return codes and timeout
In the Win32 app properties, review:
Apps > Windows > select app > Properties > Program
Apps > Windows > select app > Properties > Return codes
Make sure common installer return codes are mapped correctly:
| Return code | Meaning | Intune handling |
|---|---|---|
0 | Success | Success |
3010 | Soft reboot required | Soft reboot |
1641 | Hard reboot initiated | Hard reboot |
1603 | Fatal MSI error | Failed |
1618 | Another install in progress | Retry or failed depending on policy |
If the installer normally takes 25 minutes on older hardware, set the Intune install timeout above that reality. But use this carefully. Extending the timeout is valid for slow installs; it is not a fix for a command that never returns.
Validate detection after the install finishes
After solving 0x87D300C9, run detection. Intune still needs proof that the app installed. If detection is wrong, the next failure may look like a different error.
Check the same evidence your detection rule uses:
# File detection example
Test-Path 'C:\Program Files\Contoso\ContosoClient.exe'
# Registry detection example
Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Where-Object DisplayName -like '*Contoso*' |
Select-Object DisplayName, DisplayVersion, PSChildName
# 32-bit app on 64-bit Windows example
Get-ItemProperty 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' |
Where-Object DisplayName -like '*Contoso*' |
Select-Object DisplayName, DisplayVersion, PSChildName
If the install now exits cleanly but Intune still reports failure, switch to a detection-rule investigation.
Graph and PowerShell checks for blast radius
Use Microsoft Graph PowerShell to identify whether this is one device or a broader package issue. The exact app reporting endpoints can change, but the workflow is consistent: find the app, inspect device install states, then compare failures by OS build, device model, and assignment group.
Connect-MgGraph -Scopes 'DeviceManagementApps.Read.All','DeviceManagementManagedDevices.Read.All'
$AppName = 'Contoso VPN Client'
$App = Get-MgDeviceAppManagementMobileApp -Filter "displayName eq '$AppName'"
$App | Select-Object Id, DisplayName, CreatedDateTime, LastModifiedDateTime
For a quick local export from the Intune admin center, use:
Apps > Windows > select app > Monitor > Device install status > Export
Look for patterns:
- Only Company Portal installs fail, but required installs succeed.
- Only standard users fail, but ESP or system context succeeds.
- Only one hardware model fails because the installer waits on a driver prompt.
- Only remote users fail because the package tries to reach an internal share.
- Only devices with another install in progress fail because MSI is locked.
Those patterns tell you whether to fix the package, the assignment, prerequisites, network access, or install timing.
Prevention
To avoid 0x87D300C9 in future Intune Win32 deployments:
- Test every install command as
SYSTEMbefore uploading the final package. - Prefer MSI packages with explicit
msiexec /i,/qn,/norestart, and/L*vlogging when available. - For EXE installers, document the vendor’s silent switches in the package folder.
- Always return the child process exit code from wrapper scripts.
- Never call installers from a user profile, mapped drive, or temporary download path.
- Log to
C:\ProgramDataso the Intune Management Extension can write and admins can collect the file later. - Keep detection rules separate from install fixes. Fix one failure mode at a time.
- Pilot to a small dynamic group before assigning broadly.
- Export failed device states after the pilot and group failures by model, OS build, user context, and network location.
- Keep the
.intunewinsource folder under version control with install, uninstall, and detection scripts.
Field-tested remediation plan
Use this sequence when production users are blocked:
- Pause expansion of the assignment. Do not delete the app unless the package is unsafe.
- Pick one failed device with the exact
0x87D300C9message. - Reproduce the install as
SYSTEMusing the exact command from Intune. - Add a wrapper script that waits, writes logs to
C:\ProgramData, and returns the real exit code. - Verify the wrapper returns
0or another mapped code. - Confirm detection succeeds locally.
- Replace the Intune install command or upload a revised
.intunewinpackage. - Deploy to a test group first.
- Review
AppWorkload.logand the Intune device install status. - Resume broad assignment only after the test group reports installed.
Sources
- Microsoft Learn: Troubleshoot Win32 Apps in Microsoft Intune.
- Microsoft Learn: Support Tip - Understanding the flow behind deployment, delivery, and processing of a Win32 application through Intune.
- Microsoft Q&A:
The unmonitored process is in progress, however it may timeout. (0x87D300C9)for Intune Win32 app deployment through Company Portal.