Most Windows apps you deploy with Intune end up as Win32 apps: an installer wrapped into a .intunewin file, plus the rules that tell the Intune Management Extension (IME) when to install it and how to know it worked. In this post I'll walk through packaging with the Microsoft Win32 Content Prep Tool, the program settings that matter (install context, restart behaviour, return codes), requirement and detection rules that hold up, and piloting the app before it reaches everyone.
Prerequisites#
- Devices on Windows Pro, Enterprise or Education that are Microsoft Entra joined, Entra registered or hybrid joined and enrolled in Intune. The IME installs itself the first time a Win32 app or PowerShell script is targeted at the device or user.
- An installer that runs fully silently. Intune doesn't support interactive installs, and workarounds that show UI in the user's session (such as ServiceUI) are explicitly unsupported.
- The latest Microsoft Win32 Content Prep Tool (
IntuneWinAppUtil.exe), downloaded as a .zip from Microsoft's GitHub repository. Package size is capped at 30 GB per app.
Step-by-step#
1. Lay out the source folder#
The tool compresses everything in the source folder, including subfolders, so keep it clean: only the installer and the files it needs, with the tool itself somewhere else. A simple layout:
C:\Packaging\Tool\IntuneWinAppUtil.exe
C:\Packaging\ContosoAgent\Source\ContosoAgent.msi
C:\Packaging\ContosoAgent\Source\config\settings.xml
C:\Packaging\ContosoAgent\Output\If the installer needs a supporting file, place it in a subfolder and reference it with a relative path (for example config\settings.xml) in the install command.
2. Build the .intunewin file#
Run the tool with no parameters and it prompts for each value, or pass them on the command line:
IntuneWinAppUtil.exe -c C:\Packaging\ContosoAgent\Source -s ContosoAgent.msi -o C:\Packaging\ContosoAgent\Output -q| Parameter | Meaning |
|---|---|
-c | Setup folder; everything inside is compressed |
-s | Setup file, such as setup.exe or setup.msi |
-o | Output folder for the .intunewin file (created if missing; an existing file is overwritten) |
-q | Quiet mode |
-h | Help |
For an MSI, the tool reads the product code and version, so when you upload the file Intune pre-fills the install command, uninstall command and an MSI detection rule.
3. Create the app and set the program options#
In the Intune admin center go to Apps › All Apps › Create, choose Windows app (Win32) and upload the package. On the Program page:
- Installer type: Command line is the classic choice. You can instead upload a PowerShell script (up to 50 KB) as the installer; Intune runs it in the app's context and reads its return code.
- Install command for an MSI:
msiexec /i "ContosoAgent.msi" /qn /norestart. For an EXE use the vendor's silent switch, for examplesetup.exe /quietor/S; the vendor's documentation tells you which. - Uninstall command:
msiexec /x "{PRODUCT-CODE-GUID}" /qn /norestart. Environment variables aren't expanded here, so wrap anything that needs them in a script inside the package. - Installation time required: 60 minutes by default, 1,440 maximum; Intune fails the install if it runs longer.
- Install behavior: System installs machine-wide with nobody signed in and is right for almost every corporate app; it's required for Entra registered devices. User installs per user and fails if the installer needs rights a standard user lacks.
- Device restart behavior: Determine behavior based on return codes restarts on a hard-reboot code and notifies on a soft-reboot code; No specific action suppresses MSI restarts; App install may force a device restart lets the installer decide (a hard-reboot code schedules a restart in 120 minutes); Intune will force a mandatory device restart always restarts after success.
Watch out: Calling powershell.exe in an install command starts 32-bit PowerShell. Use %SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File Install.ps1 to get a 64-bit process, otherwise registry and file paths land in the WOW6432Node and Program Files (x86) locations.
4. Return codes#
Intune adds a default set that covers Windows Installer behaviour: 0 and 1707 mean Success, 3010 is a Soft reboot (the next app can still install), 1641 is a Hard reboot (nothing else installs until the restart) and 1618 is Retry, which makes the IME try again three times, five minutes apart. Anything else is a failure. Add the vendor's own codes if an EXE returns something different for "already installed".
5. Requirement rules#
The Requirements page always asks for Operating system architecture and Minimum operating system; disk space, memory, logical processors and CPU speed are optional. Additional rules can check a File, a Registry value or run a Script whose output you compare against a value. A device that fails a requirement shows as not applicable rather than failed, which is what you want for "only where the old agent exists".
6. Detection rules#
Every detection rule you add must be true for Intune to consider the app installed, so add one good rule rather than three fragile ones:
- MSI: product code, optionally with a product version check. Only one MSI rule is allowed.
- File: folder path plus file or folder name, checked for existence, date, version or size. Tick Associated with a 32-bit app on 64-bit clients for apps under Program Files (x86).
- Registry: key path such as
HKLM\SOFTWARE\Contoso\Agent, a value name (leave empty to test the key itself) and a comparison. - Custom script: detected only when the script exits
0and writes something to STDOUT. Any STDERR output means "not detected" even if the exit code is 0. Microsoft recommends saving the script as UTF-8 with BOM.
For a Required assignment, Intune re-offers an app it can't detect within roughly 24 hours, so a wrong rule turns into a loop of reinstalls. Build the rule from a device where you ran the installer manually.
7. Dependencies, supersedence and assignment#
Dependencies become available once the app is uploaded: a Win32 app can depend only on other Win32 apps, up to 100 apps in the whole graph including itself, and Automatically install (the default) installs the dependency even where it isn't assigned. Supersedence lets a new version update (leave Uninstall previous version off) or replace (turn it on) an older app, with a limit of 10 apps in a chain.
Assignments come in three intents: Required, Available for enrolled devices (Company Portal) and Uninstall. Required assignments also take end-user notifications, an availability time, an installation deadline and a Delivery Optimization priority.
Verify#
- Assign the app as Required to a group of one or two pilot devices, then sync from Settings › Accounts › Access work or school or Company Portal.
- In the admin center, open the app and check Device install status. "Installed" means the install command returned a success code and detection passed.
- On the device, open
AppWorkload.loginC:\ProgramData\Microsoft\IntuneManagementExtension\Logsand search for the app's ID to see the requirement check, download, return code and detection result. - Test the Uninstall intent on the same device, and test supersedence by installing the old version first.
Tips & gotchas#
- Test the install command in a prompt running as SYSTEM (PsExec
-s) before packaging; most "works for me" failures are user-profile paths or prompts that only appear under SYSTEM. - Use
/norestartand let Intune's restart behaviour decide; installers that reboot on their own break the Enrollment Status Page flow. - Apps that update themselves need version-tolerant detection ("greater than or equal to"), or you'll see
0x87D1041Conce the vendor's updater runs. - Apps in a dependency relationship can't be deleted and lose the Company Portal uninstall button until the relationship is removed.
- If Multi-Admin Approval is enabled, create the app first and add any PowerShell installer script afterwards.