This blog dives into how Intune handles MSI app deployments when you choose App Install Context: User, and why that setting doesn’t always do what you think it does.
We’ll look at how the EnterpriseDesktopAppManagement CSP triggers MDMAppInstaller, how the install context is determined, and why apps like Zoom or 7-Zip can still end up in C:\Program Files even when deployed as a user install. By the end, you’ll see that the secret lies inside the MSI itself, not Intune.
Introduction
It all started with something that shouldn’t have happened. We uploaded a Line-of-Business MSI app to Intune, set the App install Context to User.
With the app install context set to user, we expected it to install inside the user profile under AppData\Local\Programs. Instead, it showed up in C:\Program Files, which is the device context location.
That didn’t make sense. The first test was with Zoom, which supports both per-user and per-machine installs. Normally, when you run the installer manually without elevation, it installs in the user’s profile. But when Intune pushed it as an LOB app with Install behavior: User, it went straight into Program Files. At first, it seemed like a packaging issue. Until we tested another one… 7-Zip. Same result.
Before diving in
We know mixing MSI-based LOB apps with Win32 apps isn’t recommended. It can break detection, dependencies, or uninstall logic.
Still, this wasn’t about mixing app types. This was about understanding why a User install wasn’t really a user install at all. And technically, Microsoft does something similar, the Device Inventory Agent and EPM Agent are also deployed through the same MDMAppInstaller mechanism that handles LOB MSI installs. Which could cause issues during Autopilot as well?

Despite Microsoft’s own advice against doing so, converting to Win32 is better. Read this blog for the full picture! But sometimes you just need to see what’s really happening under the hood first.
The confusing “User” App Install Context setting
That Install behavior dropdown in Intune looks simple: Device or User. It sounds like it decides where the app installs… Program Files or AppData, but it doesn’t. It only decides who runs the installer. Behind the scenes, it only decides who executes the installer, not how the MSI installs. When Intune delivers a line-of-business MSI, it uses the EnterpriseDesktopAppManagement CSP, which sets everything in motion.
The CSP flow that defines App Install context
When Intune delivers the policy, the CSP node is written under: HKLM\SOFTWARE\Microsoft\Provisioning\NodeCache\CSP\Device\MS DM Server\Nodes\<PolicyID>\NodeUri. That value points to either: ./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/{ProductGUID}
or ./User/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/{ProductGUID}
Depending on whether you chose Device or User App install context.
After that, the device writes an entry to: HKLM\SOFTWARE\Microsoft\EnterpriseDesktopAppManagement\<SID>\MSI\<ProductGUID>
If the install behavior is Device, the SID is always the placeholder: S-0-0-00-0000000000-0000000000-000000000-000
If it’s User, it uses the logged-in user’s real SID. This triggers MDMAppInstaller, which monitors those registry keys for new jobs and starts the install process based on that information.
The App Install Context Enforcement path
Once MDMAppInstaller detects a new MSI job, it checks the assignment type.
If it’s Device, it runs as SYSTEM.
If it’s User, it duplicates the user’s token and uses CreateProcessAsUserW to start the installer inside the user’s session.
So yes, the User setting in Intune really does launch msiexec.exe using the user’s token.
But that’s all it changes.
Why it installs in Program Files even as it runs as a user process
When you check Event Viewer or Procmon, everything looks correct:
msiexec.exe runs as your user, shows a medium integrity level, and the command line even points to a path under your AppData folder.
But that process was still spawned by SYSTEM through MDMAppInstaller.exe.

When MDMAppInstaller calls CreateProcessAsUserW, the process starts in your session but inherits SYSTEM’s privileges. So while it looks like a user process, it still inherits elevated access from SYSTEM.
The result: msiexec.exe appears to run as a normal user but still has permission to write to protected folders, including Program Files. That’s why even non-admin users can end up with “user” installs sitting in C:\Program Files.
What the job actually executes
Every MSI job contains the download path, the install state, and metadata for MDMAppInstaller.
When the installer is triggered, MDMAppInstaller builds and runs a command line similar to this:
C:\Windows\system32\msiexec.exe /quiet /qn /i "<path>\app.msi"
If the install behavior is Device, MDMAppInstaller automatically adds: ALLUSERS=1
forcing a per-machine installation to C:\Program Files.
If the install behavior is User, it drops that parameter completely, no ALLUSERS=1, no MSIINSTALLPERUSER=1.
That leaves the MSI itself to decide what to do next. So the difference between Device and User isn’t where it installs, it’s just whether that extra flag gets added.
| Install Behavior | Runs As | Parameter | Result |
|---|---|---|---|
| Device | SYSTEM | ALLUSERS=1 | Per-machine |
| User | User token (via SYSTEM) | (none) | Depends on MSI |
The MSI decides the App Install Context
Once msiexec.exe starts, Windows Installer looks only at the MSI’s internal Property table.
| Property | Description |
|---|---|
| ALLUSERS=1 | Always installs system-wide |
| ALLUSERS=2 | Chooses based on privileges (default) |
| MSIINSTALLPERUSER=1 | Forces per-user install (LocalAppData\Programs) |
If the MSI doesn’t include MSIINSTALLPERUSER=1, it won’t install per-user, even if Intune says “User.” That’s exactly why both Zoom and 7-Zip ended up in Program Files.
Following the process in Procmon
When we traced MDMAppInstaller.exe with Procmon, the event chain looked like this:
MDMAppInstaller.exe → msiexec.exe (User: AzureAD\<username>)
Command Line:
C:\Windows\system32\msiexec.exe /quiet /qn /i "C:\Windows\system32\config\systemprofile\AppData\Local\mdm\<GUID>.msi"
So it really was running as the user.
It just wasn’t a true per-user install because the MSI lacked the correct property.
Opening 7-Zip in Orca
Knowing how the MDMAppInstaller code kicks off the process, and how it decides to install the app in user device context, we opened up the 7-zip MSI with the Orcaa tools. Inside 7z2501.msi, the Property table contained: ALLUSERS = 2

The draw.io comparison
We then tried the same with draw.io, which we knew was getting installed in the localappdata when selecting the user install context. The moment we opened the draw.io MSI
Its Property table showed:
ALLUSERS = 2
MSIINSTALLPERUSER = 1
The missing msiinstallperuser in the 7-Zip MSI explained why it wasn’t being installed in the user’s localappdata folder, but in the program files folder instead.
Changing the 7-Zip properties with Orca
After spotting the MSIPerinstaller=1 in the draw.io, things started to make sense. From there on, we reopened the 7-zip MSI and added a single line using Orca: MSIINSTALLPERUSER = 1

Saved the MSI and redeployed it through Intune with User behavior.
This time, it installed into: C:\Users\<username>\AppData\Local\Programs\7-Zip
The difference? Just one property inside the MSI.
Why adding parameters in Intune doesn’t change it
At this point, you might think you can fix it by forcing MSIINSTALLPERUSER=1 in the command line.
It seems that even if you add the MSIINSTALLPERUSER=1 to the install command in Intune, MDMAppInstaller strips it. Its argument builder only allows /i, /qn, /quiet, and /L*v.
Anything else is removed before execution. That’s why manually editing the MSI worked, but adding parameters in Intune didn’t.
What we learned about the App Install Context
- The “User” install behavior in Intune changes who runs the installer, not where it installs.
- Even if the process runs under the user account, it inherits SYSTEM’s privileges through MDMAppInstaller.
- When using Device, MDMAppInstaller explicitly adds
ALLUSERS=1to force a per-machine install. - When using User, it adds nothing, the MSI decides what to do.
- To truly install per-user, the MSI must define
MSIINSTALLPERUSER=1.
The conclusion
This isn’t really a bug, it’s a design gap.
The User install behavior in Intune doesn’t guarantee a per-user installation.
It only affects execution context, not installer behavior.
If the MSI lacks MSIINSTALLPERUSER=1, it will ignore the user setting and install system-wide.
To fix that, you can either:
- Modify the MSI’s Property table in Orca and add
MSIINSTALLPERUSER=1, or - Convert it to a Win32 app where you control the full command line.
So if you ever see your User installs ending up in Program Files, check the MSI itself, not Intune.