This is the seventeenth in a series of notes about UAC in MSI. Per the earlier caveat, these are just my notes and not an official position from the Windows Installer team. The previous entries

  1. Introduce...
    1. ...the UAC in MSI Notes series
    2. view of the root problem
    3. ...the conflicting per-user definition
    4.'ll be just like Managed Installs
    5. ...the jagged edge to user
    6. relief providing framework
  2. Architecture Insights
    1. The "Saw Tooth" Diagram
    2. Credential Prompt and Permissions
  3. Common Package Mistakes
    1. The AdminUser Mistake
    2. Modify System with InstallUISequence Custom Action
    3. Modify System with InstallExecuteSequence Custom Action Outside of Script
    4. The NoImpersonate Bit Mistake
  4. More Architectural Insights
    1. My "Four Square" Diagram
    2. Challenges for a Beautiful Custom Action
    3. O Whitepaper, Where Art Thou?
    4. Read the Friendly Manual
This entry will start a new section specifically focused on Question and Answers that often come up in the UAC in MSI dialogs.  First up, should I write my installer as a Standard User install?  If yes, how?

Should I write my installer as a Standard User Install?

It depends.  The dependencies include

  • Whether the architecture of the application being installed will work from a Standard User installed location.  There are places in the system that will always require admin rights to install to.  If your application must go there, there's no use in going any further. 
  • If you're going to have an application that needs administrator's permission to run, you don't want it in a per-user location.  An application that is going to be elevated should install to a location that is not Standard User tamper-able.  Were a program that ran elevated tamer-able by the user, a black hat could modify the binary in the per-user context and then elevate to compromise the entire machine.

When talking to customers, package producers (generally ISVs) have told me they don't want per-user for these reasons

  • Installing to locations the user has the ability to alter might reduce the confidence the package producer has for the integrity of the install.  This can affect support costs as well as computational correctness under a regulatory environment (lawyers, accounts, food and drug companies, government agencies, etc)
  • Multiple instances of an install means there is duplicate copies of binaries on the machine which wastes disk space.  A per-machine install creates a single copy of common binaries for all users thus saving space.
  • Software is less secure because updating behavior has to be done for each user on the machine.  In other words, the occasional user on the machine can made the machine vulnerable because they are not on the machine often enough to keep the software they use up to date.

When talking to customers, package consumers (generally corporations) have told me they

  • Want programs in locations users can't tamper with.  User tampering is a major source of support costs.
  • Centralized install, servicing, and uninstall from a central IT department are all more challenging when the apps are just in the users profile.  There are numerous conditions where it is known not to work at all.

The one case Standard User makes the most sense is viral applications that are being distributed via the web.  Even for these applications one has to ask the question: do you want to eventually grow-up to be distributed inside a corporation? 

How do I build a Standard User package?

This takes a bit of work to make a package install only to the locations a Standard User has permission. Some of the requirements are


  1. Use a Type 51 Custom Action in the InstallUISequence to always unset the ALLUSERS (the per-user option)
  2. Files must be written only to folders that Standard User has access to.  Assuming the ALLUSERS is always set to the per-user setting, you can use the redirectable folder properties but not ProgramFilesFolder as it does not redirect on per-user.
  3. Install app to a location under LocalAppDataFolder
  4. All registry settings should be written to HKCU which is 1 in the Registry Table’s Root column.
  5. Flip bit 3 of the word count property in the summary information stream to signal no credential prompt is required.
  6. If you have a bootstrapper (typically named setup.exe), manifest the requestedExecutionLevel to run asInvoker.
  7. Pass ICE Validation as the ICEs have checks for incorrectly mixing per-user and per-machine state.
  8. Test both from a Standard User account and from an elevated command prompt to confirm behavior.
  9. Provide your users’ documentation of the user specific nature of the package as this is atypical in today’s application installs.