The Win32 app shows "Failed" in Intune. The install actually completed — the endpoint is just sitting there waiting for a reboot it was never told to force, or it force-rebooted a user mid-meeting because a wrapped EXE returned the wrong exit code. Reboot handling is the part of Win32 app deployment everyone treats as an afterthought, right up until it either breaks a deployment status or interrupts a user at the worst possible moment.
This article covers what 3010 and 1641 actually tell Intune to do, why installers frequently return the wrong one, and how to configure Win32 apps so reboots happen on your terms instead of the installer's.
Fast Verdict Matrix
| Behavior | Legacy EXE Behavior | MSI / Well-Configured Behavior |
|---|---|---|
| Reboot signal Exit code returned | Wrapper picks whatever code the vendor bootstrapper happened to return — often 0 even when a reboot is actually pending, because the bootstrapper swallows the inner installer's real code. | A native MSI returns the standard Windows Installer codes: 3010 (soft, reboot required) or 1641 (hard, reboot initiated) — consistent across every MSI ever built. |
| Who controls the reboot Timing | Some EXE installers call shutdown.exe or InitiateSystemShutdown directly inside the install process, rebooting the endpoint immediately regardless of what Intune's restart grace period says. | 3010 hands control back to Intune, which applies the configured restart grace period and end-user notification before anything happens. |
| Return codes tab Default configuration | Out of the box, only 0, 1707, 3010, 1641, and 1618 are pre-mapped. A wrapped EXE that returns its own custom reboot code (common with InstallShield and Squirrel) needs that code added manually or Intune reports a false failure. | MSI installers only ever need the defaults — no custom mapping required, because the codes are standardized by the Windows Installer engine itself. |
The Rule of Thumb
- 3010 is a request; 1641 is an event that already happened.
3010tells Intune "install succeeded, reboot is pending" and lets Intune's restart policy decide when to act on it.1641tells Intune the installer already triggered the reboot itself — Intune just records it as a hard-reboot success after the fact. - Never let a wrapped EXE call the reboot directly. If the installer forces a restart outside of Intune's control, the grace period, user notification, and deadline settings configured in the Win32 app profile are bypassed entirely — that is how a background patch turns into an unplanned reboot in the middle of a user's workday.
The Fix: Standardized Reboot Signaling
The pattern behind most reboot problems in Intune is the same one behind most exit code problems generally: every EXE vendor's bootstrapper decides for itself what to return and when to reboot, and none of those decisions were made with Intune's restart policy in mind. The common workaround is a PowerShell wrapper — PSAppDeployToolkit or a custom script — that intercepts the installer's real exit code, suppresses any self-initiated reboot call, and translates the result into 3010 or 0 before handing control back to Intune. That works, but it means writing and maintaining a translation layer per installer, and re-verifying it every time the vendor changes their bootstrapper.
InstallMage removes the translation layer by converting the source EXE into a native MSI in the first place. A real MSI never calls shutdown.exe on its own — the Windows Installer engine returns 3010 or 1641 through the standard mechanism, so Intune's restart grace period and notification settings apply automatically, every time, without a PSADT reboot-suppression block to write and keep in sync.
Deep Dive
What 3010 and 1641 Actually Tell Intune
Both codes are Windows Installer standards, not Intune inventions — Intune just reads them and reacts. 3010 (ERROR_SUCCESS_REBOOT_REQUIRED) means the install completed and something on disk or in the registry needs a restart to take effect, but nothing has told the OS to restart yet. Intune marks the deployment a soft-reboot success and, depending on the app's assignment settings, either prompts the user with the configured grace period or defers the restart to the next scheduled maintenance window.
1641 (ERROR_SUCCESS_REBOOT_INITIATED) means the installer itself already called the restart — the reboot is not pending, it is in progress or about to be. Intune records this as a hard-reboot success and does not layer its own grace period on top, because there is nothing left to schedule. The practical difference: if you see users reporting an install that rebooted them without warning, check whether the return code Intune received was actually 1641, or whether the installer forced a restart out-of-band and merely happened to also return something Intune mapped to success.
Both codes are in the Win32 app's Return codes tab by default — 3010 as soft reboot, 1641 as hard reboot. If your installer returns a different code for a pending restart (InstallShield and some Squirrel-based installers use their own values), that code needs to be added manually as a soft or hard reboot type, or Intune treats it as an unmapped failure. For the full list of codes you will encounter beyond just the reboot pair, see the Intune Win32 app exit codes guide.
Why Wrapped EXEs Get This Wrong
A wrapped EXE's exit code is only as reliable as the bootstrapper that produced it, and reboot signaling is one of the most common places that bootstrapper lies. Three failure patterns show up repeatedly:
- The bootstrapper swallows the inner installer's code. A two-stage EXE runs an embedded MSI that correctly returns
3010, but the outer bootstrapper only propagates0or1based on whether its own process exited cleanly — the reboot-required signal never reaches Intune at all, and the endpoint sits in a stale state until something else triggers a restart. - The installer forces the reboot itself. Some bootstrappers call
InitiateSystemShutdownorshutdown.exe /rdirectly as the last step of installation, bypassing Intune's restart grace period entirely. This is the scenario that generates help desk tickets — a user is mid presentation when a background Win32 app assignment reboots their machine with no warning, because the installer never gave Intune the chance to apply its notification settings. - A custom reboot code that is not mapped. Older InstallShield builds and some Squirrel-packaged apps return vendor-specific codes for "success, restart needed" instead of
3010. Unless that specific code is added to the Return codes tab as a soft or hard reboot type, Intune treats a successful install as an outright failure.
Verify actual behavior before trusting documentation: run the installer under psexec -i -d -s cmd.exe in a test VM, capture the real exit code with echo %errorlevel%, and watch whether the machine restarts on its own. That tells you definitively whether you are dealing with a code-mapping problem or an out-of-band reboot problem — the fix is different for each.
Configuring Restart Behavior in Intune
Once the exit code is correct, restart behavior is controlled in two places on the Win32 app: the Return codes tab (what 3010/1641 mean) and the tenant-wide or app-specific restart settings under Devices > Compliance > Notifications and the app's own Restart behavior option (Determine behavior based on return codes, No specific action, App install may force a device restart, or Intune will force a mandatory device restart). Leaving this on the default Determine behavior based on return codes is correct for almost every app — it lets 3010 and 1641 drive the outcome instead of a blanket policy.
The setting that actually prevents the disruptive-reboot complaint is the grace period and countdown notification, configured per assignment. A soft-reboot (3010) app respects that countdown; a hard-reboot (1641) app, or an EXE that force-restarted outside of Intune's awareness, does not. That is the practical reason to push installers toward returning 3010 rather than initiating their own restart — it is the only one of the two that leaves the end-user experience under your control. For the install-context settings that interact with restart behavior (a per-user install can behave differently on reboot than a per-machine one), see the per-machine vs per-user context guide.
Frequently Asked Questions
What is the difference between exit code 3010 and 1641 in Intune?
3010 means the install succeeded and a reboot is required but has not happened yet — Intune applies its configured restart grace period before prompting the user. 1641 means the installer already triggered the reboot itself — Intune records it as a hard-reboot success with no grace period to apply, since the restart is already underway.
Why did an Intune deployment reboot a user's machine without warning?
The installer most likely called shutdown.exe or an equivalent Windows API directly instead of returning 3010 and letting Intune handle the restart. When that happens, Intune's configured grace period and end-user notification are bypassed entirely because the reboot was never under Intune's control in the first place. Test the installer under SYSTEM with PsExec to confirm whether it force-restarts on its own.
My installer returns a custom code for "success, reboot needed" — how do I make Intune recognize it?
Open the Win32 app in the Intune portal, go to the Return codes tab, and add the specific code your installer returns with type Soft reboot (if the reboot is only pending) or Hard reboot (if the installer already initiated it). Confirm the exact code first by running the installer under psexec -i -d -s cmd.exe and checking %errorlevel%, since vendor documentation for non-standard reboot codes is frequently wrong or outdated.
Reboot handling fails quietly because it looks like a success either way — the app shows installed, the difference is only in who controlled the timing and whether the user was warned. Getting 3010 versus 1641 right, and keeping the reboot call inside Intune's hands instead of the installer's, is what separates a scheduled maintenance-window restart from a help desk ticket. For the broader set of exit codes this pair belongs to, see the Intune Win32 app exit codes guide.