This is the twenty-third 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
- Architecture Insights
- Common Package Mistakes
- More Architectural Insights
- Conversations with Customers
- Should I write my installer as a Standard User install? If yes, how?
- When General Custom Action Mitigation Fails
- How do I get the shield on the advertised shortcut?
- How do I troubleshoot UAC in MSI via the log?
- Do I need to consider "this" when I'm designing for UAC in MSI? Generally, no.
- Is "this" intentional? If so, why?
This entry continues a section specifically focused on Question and Answers that often come up in the UAC in MSI dialogs. For this entry the topic is: was "this" intentional? If so, why?
How to Build Packages that work for both Standard User and Per-Machine?
While rolling out the User Account Control (UAC) support for Windows Installer (MSI), we’ve been having a common conversation about how to build a single install package that works for both broad web and managed corporate deployment. The thread below homogenizes the questions into an imaginary ISV and the common scenario that drives this particular conversation.
Imaginary Independent Software Vendor (ISV):
Tim is an ISV who provides both a remote browser only and locally installed client experience where both are coupled with Tim's server side backend. The locally installed Tim client harnesses the horsepower of the client node providing a richer Tim experience.
ISVs Market Realities:
Accessing the Tim client market, Tim needs an Install experience that installs to either all-Standard-User or no-Standard-User writable locations. The all-Standard-User-writable install maximizes for reach while accepting a user could mess with integrity of the binaries. The no-Standard-User-writable install maximizes integrity of the binaries while accepting there will be less reach due to some (perhaps many) unable to get their administrators permission.
ISVs Reduction of UAC Messages:
Tim has reduced the messages from the UAC evangelists to:
- Microsoft expects the eventual response to any Over the Shoulder (OTS) UAC prompt will be ‘no’
- Microsoft expects very few users will run as Protected Admin (PA) there by making almost all prompts OTS
- Microsoft expects Protected Admin to be rare enough that it’s just a speed bump for highly savvy users
ISVs Derivation from UAC Messages:
Tim is willing to assume that a Protected Admin will always elevate and a pure Standard User (thus an OTS prompt) will never elevate.
From a single install package, Tim wants to figure out whether the person initiating the install is Protected Admin or plain Standard User. If Protected Admin, then the install package will configure itself to run as no-Standard-User-writable; else (a plain Standard User), the install package will configure itself to run as all-Standard-User-writable.
Initial ISV Ask:
Please provide me a way to query if the Standard User is plain Standard User or Protected Admin user so that I can execute on this scenario.
A couple of things to consider
- First, the official recommendation from the MSI team is that one should use multiple packages as this maps into the majority of the scenarios that were designed and tested for in MSI 4.0 development. We’ve found dual mode packages are difficult for ISVs to get right for all scenarios.
- Second, it's by-design that UAC does not allow a way to query whether a Standard User is plain Standard User or Protected Admin user so that I can execute on this scenario. UAC encourages ISVs to provide users the maximum context so that they can make an informed decision at the consent prompt. UAC does also encourage ‘when you don’t know, say no’.
Second ISV Ask:
The Windows Installer team has actively encouraged ISVs not to use bootstrappers if they don’t need to and we’ve determined separate packages have no collisions so they can be easily merged as long as we have a decision point to chose between the paths. Isn’t there some way to make this work.
Assuming you’re willing to take the risks of the road less traveled, there is a mitigation path that involves
- set bit 3 in the word count property of the summary information stream and set the MSIUSEREALADMINDETECTION property (not yet published in the online SDK, internal copy below) and author the package to use AdminUser to determine if the context is already admin. If AdminUser is true, install to the no-Standard-User-writable location; else (AdminUser is false), install to the all-Standard-User-writable location.
- for non-corporate distribution, just provide the MSI and the general case will be all-Standard-User-writable install. Warning: you’ll need to figure out how to account for the potential for user tampering of the binaries.
- for corporate distribution, provide the MSI along with instructions on how to invoke the plain .MSI in common corporate deployment systems (Group Policy, SMS, Altiris, Tivoli, OpenView, etc) that may require the plain .MSI. The secret sauce to this scenario is that most corporate deployment systems invoke the package from a client running as Local System on the client node.
- for the occasional home administrator that does not have corporate distribution tools, provide a bootstrapper (commonly called a setup.exe) that is manifested to run as admin <requestedExecutionLevel level="Administrator" /> that will invoke the MSI.
This is not the majority case for software distribution today so we are unable to provide the same assurances we would provide were you to follow the recommended path.
Third ISV Ask:
Is there a way to avoid the setup.exe bootstrapper in the home administrator case?
You could recommend folks run the install from an elevated command prompt.
Preliminary SDK page:
Set the MSIUSEREALADMINDETECTION property to 1 to request that the installer use actual user information when setting the AdminUser property. When running on Windows Vista, the Privileged and AdminUser are the same. Authors should used the Privileged property in new packages. Legacy packages that require distinct Privileged and AdminUser properties can restore the difference by setting the MSIUSEREALADMINDETECTION property.