Windows Installer can install an application Setup package in one of two contexts: a “Per-Machine” installation is performed to allow all registered users of the computer to access and use the application. A “Per-User” installation is performed for the single user that is executing the application Setup – it is not available for use by any other registered user of the computer.
Historically with Windows XP and earlier Operating Systems, the “Per-User” or “Per-Machine” context referred to ensuring the Shortcuts/Icons were visible to just the single user or all users. There were implied restrictions when you selected either of the installation contexts – but there was no overt restriction during the installation.
With the introduction of Windows 7 and the more stringent UAC (User Access Control) restrictions, we are seeing more frequently the need for an installation package to “Run as Administrator”. This is because standard users now have more limited privileges and are being prevented from installing into the “Per-Machine” context without first obtaining permission.
With this posting I hope to clear up and improve your ability to address these requirements within your installation packages.
Executing an installation package in the “Per-User” context
On a machine that is setup for multiple users, the application installation package is run by a specific user and no other user can access that application. The other users don’t even see any installed artifacts – so there is no evidence of:
- Application files
- All application files would need to be written to Per-User specific folders that are not visible to other users – for example anything written to “c:\Program Files\ISI” would be visible to other users.
- Entry in the Add/Remove Control Panel
Obviously the application would need to be specifically designed to register files in HKCU\CLASSES and registry entries only added to HKCU\Software\xx for application access.
How does the installation package announce that it is to be run as “Per-User”?
There is a MSI property that can be placed within the application package that allows the application setup to announce to Windows Installer that it wants to be installed “Per-User”.
The ALLUSERS MSI property can be set so that the application package will be run in the “Per-User” context. Both by the absence of the ALLUSERS property or the property is present but the value is set to NULL (ALLUSERS=””) will force the installation package to be run in the “Per-User” context.
On Vista, you could still force the installation package to be run as “Per-User” as we have discussed. Note that the user’s privileges are immaterial when running in the “Per-User” context – but once the decision is made that the install will be run in the “Per-User” context (By setting the ALLUSERS=”” or not having the property), the User rights issue makes no difference. But remember, the install starts but it WILL FAIL
if the user doesn’t have Admin rights and the install tries to write to any machine-wide resources.
If a user has Admin rights, but the install is run in the “Per-User” context, with the Admin rights, any accidental writing to machine-wide resources will be allowed.
On Windows 7, the ability to run as “Per-User” is constrained by the specifics of the package. Essentially these points are important for an application setup to be eligible for a “Per-User” installation context:
All files are installed to Per-User folders, such as
- “C:\Documents and Settings\$User\Local Settings\Application Data” on WinXP
- “C:\Users\$User\AppData\Roaming” on Windows 7
- All Shortcuts and the Add/Remove Control Panel entry are only seen by that user
- All registry entries (Application data and registration) are made to HKEY_CURRENT_USER hive.
- No registry entries are made to machine-wide registry keys, such as HKEY_LOCAL_MACHINE or HKEY_CLASSES_ROOT hives
- The installation package cannot allow the user performing the installation package to select destination directories that are machine-wide, such as “c:\Program Files”
- All application binary file (EXE, DLL) need to be digitally signed to be allowed to be installed by “Per-User” for Windows 7.
On Windows 7, if any of the above constraints are not met, the package will be installed “Per-Machine” – this means that a “Per-User” will not be allowed!
In general, you should configure your installers to be “Per-Machine” installs (i.e. ALLUSERS=1). You should only use “Per-User” installs (i.e. ALLUSERS=””) if your installer meets the following conditions:
1. All files are guaranteed to be installed to “Per-User” folders. Most installers allow the user to choose the install location and default to ProgramFilesFolder which disqualifies them from this requirement.
2. There are not any changes being made to machine-wide Registry keys such as HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT, etc.
3. There are not any other files or folders affected by the installation that are not in “Per-User” locations.
If your installer does meet that criteria, you should also set the “Privileges required” value on the Package tab of the Project Settings screen to Limited so that the Windows Installer engine does not force a UAC elevation to take place once installation is about to begin.
Having said all of that, in practice it is very rare to design and deploy a “Per-User” installation. In general, you should keep your installers as “Per-Machine” installs.
Considerations regarding “Per-User” Installations
There are several common scenarios that an arise when the choice of “Per-User” versus “Per-Machine” is given to the user:
Major Upgrades can Fail
If you use the Upgrade code feature of Windows Installer to perform a major upgrade the detection of the existing software will fail if: (a) the original software was installed with ALLUSERS=”” and the new software has ALLUSERS=1 in its Property table or passed on the command line or (b) the original software was installed with ALLUSERS=1 and the new software has ALLUSERS=”” or ALLUSERS is not defined in the Property table or on the command line.
If two different users on the system install the software with ALLUSERS=”” they will both have their own shortcuts and Add/Remove Programs entries made (which is fine and is by design). However, if some of the files are installed to a shared location (such as ProgramFilesFolder) and one of the users uninstalls the software, the other user will not be able to use the software even though their shortcuts and Add/Remove Programs entries are still intact. In other words, the two installed instances of the software will not “know” about each other.
- Support Issues
- 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.
- IT departments 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
How to block users from installing applications “Per-User”
Setting the policy DisableMSI to 1 will block the “Per-User” install operations of dual mode packages. Setting it to 1 will also block all the uninstall/patching/upgrade of the packages that were previously installed with MSIINSTALLPERUSER=1. Setting the DisableMSI to 2 will block windows installer from doing any operations on the machine. Setting the DisableUserInstalls policy to 1 disables install/uninstall/upgrade/patching of “Per-User” applications.
Executing an installation package in the “Per-Machine” context
What does it mean if an installation package runs “Per-Machine” context?
On a machine that is setup for multiple users, the installation package is typically run by the machine administrator, and all users can use that application. They can see any application files placed in the machine-wide folder (Program Files), all shortcuts and the entries in the Add/Remove Control Panel.
Essentially these points are important for a “Per-Machine” context:
- All files are installed to machine wide folders, such as “c:\Program Files” on WinXP or Windows 7
- All Shortcuts and the Add/Remove Control Panel entry are seen by all users
- All registry entries (Application data and registration) are made to machine-wide registry keys, such as HKEY_LOCAL_MACHINE or HKEY_CLASSES_ROOT hives
- The installation package can allow the user performing the installation package to select destination directories that are machine-wide, such as “c:\Program Files”
How does the installation package announce that it is to be run as “Per-Machine”?
The setting of the MSI Property “ALLUSERS=1” dictates that an installation package is to be run in the “Per-Machine” context. This setting will force the installation package to be run in the “Per-Machine” context, but if the User does not have Admin rights the installation package fails.
On Vista, you could still force the installation package to be run “Per-Machine” by setting of the MSI Property “ALLUSERS=1” as we have discussed.
On Windows 7, you could still force the installation package to be run “Per-Machine” by setting of the MSI Property “ALLUSERS=1” as we have discussed.
If the user has only User Access privileges, Windows Installer performs a “Per-Machine” only if Admin credentials are provided to the UAS dialog box – typically by specifying “Invoker=Admin” in the setup manifest.
Creating an installation package that runs in either the “Per-User” or “Per-Machine” context
On Windows XP, you can have the ALLUSERS property set to “ALLUSERS=2”, a value that allows the Operating System to determine whether the install runs as “Per-User” or “Per-Machine” based on whether the user has Admin rights. In this scenario, the conditional logic determines that having Admin rights allows the installation package to run in the “Per-Machine” context, but limited rights forces the install to run in the “Per-User” context.
On Vista, you could still force the installation package to be run as “Per-User” or “Per-Machine” as we have discussed. But the introduction of the UAC prevented the Operating System from providing the conditional logic to determine where an installation package should be run in the “Per-User” or “Per-Machine” context (for example, setting ALLUSERS=2 and the logic checks the user’s Admin rights).
The workaround solution was to create two separate installation packages, the one that was designed for “Per-User” would have the UAC compliant bit set, while the one that was designed for “Per-Machine” did not have the UAC compliant bit set (UAC compliant bit set refers to the MSI’s Word Count row found in the Information Summary table – which must be done via the Direct Editor when using InstallShield v2009 or earlier). Once this bit is set, no UAC prompt is required and the package is installed “Per-User”. The author of the installation package would need to ensure that the shared locations (c:\Program Files) were not used since there was no “Per-User” equivalent of “Program Files”.
Windows 7 introduces a dual-Mode Package:
With Windows Installer version 5.0 installed on Windows 7, you can author a dual mode package that can be installed “Per-User” or “Per-Machine”. Setup developers that use a dual-purpose package for their application can provide their users with a choice of installation context at installation time and can remove UAC credential prompts from “Per-User” installations on Windows 7 or Windows Server 2008 R2. The development of a dual-purpose Windows Installer 5.0 package for installation on Windows 7 and Windows Server 2008 R2 is referred to as single package authoring.
Setup authors can set the MSIINSTALLPERUSER property to 1 and ALLUSERS to 2 to identify the package as a dual-purpose package. Note that MSIINSTALLPERUSER is only evaluated when ALLUSERS=2. These properties can be specified in the package, passed through the command line, modified by a transform, or – more commonly – selected through a user interface dialog.
Adhere to these Development guidelines for dual-mode packages to ensure your package can be installed in either the “Per-User” or “Per-Machine” context. Here are some crucial points from that extensive list:
Consider activating the “Per-User” option in the dialog “Ready to Install” for the user interface of your dual-purpose package that enables the user to choose the context at installation time. See the example shown:
- Validate the package using Internal Consistency Evaluators – ICEs. The package must be able to pass validation by ICE105 to be a valid dual-purpose package.
- Use the ProgramFilesFolder property in the Directory table of 32-bit Windows Installer Packages to specify the locations of directories containing 32-bit components not shared across applications. When a user installs the dual-purpose package using the “Per-Machine” context, these components are saved in the Program Files folder on 32-bit versions of Windows and in the Program Files (x86) folder on 64-bit versions of the system. The components in these directories can be accessed by all users. When a user installs the dual-purpose package on Windows 7 or Windows Server 2008 R2 using the “Per-User” context, these components are saved in the Programs folder of the current user (for example at %LocalAppData%\Programs) and can be accessed only by that user.
- Use the CommonFilesFolder property in the Directory table of 32-bit Windows Installer Packages to specify the locations of directories containing 32-bit components shared across applications. When a user installs the dual-purpose package using the “Per-Machine” context, these components are saved in the Common Files folder and can be accessed by all users. When a user installs the dual-purpose package on Windows 7 or Windows Server 2008 R2 using the “Per-User” context, these components are saved in the Common folder of the current user (for example at %LocalAppData%\Programs\Common) and can be accessed only by that user.
- Store “Per-User” configuration data for the application under \Users\username\AppData.
- Do not use custom actions in your package that require elevated privileges to run. The CustomAction table should contain no custom actions that have been marked to run with elevated privileges. For more information about elevated custom actions, see Custom Action Security.
Do not write in any global system folders. The Directory table should not contain a reference to any of the following system folder properties.
- Do not install a common language runtime assembly into the global assembly cache (GAC.) For more information about installing assemblies to the global assembly cache, see Adding Assemblies to a Package and Installation of Common Language Runtime Assemblies.
- Do not install any services. Do not use the ServiceInstall table to install a service.
Creating an installation package that runs without the UAC Dialog Box
When elevated privileges are not required to install a Windows Installer package, the author of the package can suppress the dialog box that User Account Control (UAC) displays to prompt users for administrator authorization.
This means that the application package is eligible for being installed in the “Per-User” context and conforms to these Development guidelines.
To suppress the display of the UAC dialog box when installing the application, the author of the package should do the following:
- Install the application using Window Installer 4.0 or later on Windows Vista.
- Do not depend on using elevated system privileges to install the application on the computer.
Set the MSI Property “ALLUSERS=1”
Installs the application in the “Per-User” context and make this the default installation context of the package. If the ALLUSERS property is not set, the installer installs the package in the “Per-User” context. If you do not include the ALLUSERS property in the Property table, the installer does not set this property and so “Per-User” installation becomes the default installation context. You can override this default by setting the ALLUSERS property on the command line.
- Set Bit 3 in the Word Count Summary property to indicate that elevated privileges are not required to install the application.
Setting an installation package so that it requires Administrative Privileges
There are two configuration items you can use in the InstallShield panels, one is the “Require Administrative Privileges” property in the Summary Information Stream, the other is the “Required Execution Level” property in the Release View.
Here is an explanation of what they are used for:
- “Require Administrative Privileges” indicates how the application setup manifest (which is embedded by InstallShield in the setup launched – when you specify a setup in the Media) should be configured. The Manifest controls how the operating system runs the Setup, any Setup Prerequisites and the .MSI file.
- “Required Execution Level” applies to just how the Operating System handles the .MSI file. Setting this configuration value will set the fourth bit of the Summary Information Stream’s Word Count property – which in prior to InstallShield v2010 had to be set manually.
In my experience, here’s what the two settings mean at runtime. If you launch from a Setup (Setup.exe) Windows 7 will first evaluate the directions in the manifest. If you don’t have a setup.exe, or if setup.exe runs as a limited user (either lowest privileges, or highest available on a limited account), then the User Interface Sequence MSI process (Foreground process as it were) will be launched as a limited user. If you have a Setup running with administrative privileges then the client-side MSI process will be running with administrative privileges.
Now assuming your client-side MSI process is running as a limited user, the Summary Info stream bit comes into play. If you say the MSI requires administrative privileges then when it launches the Execute Sequence MSI process (background processing), MSI will prompt for administrative privileges just like any other UAC prompt, and the Execute Sequence process will run as though you’re an administrator. If you say the MSI does not, there will be no prompt, and MSI will run as though it has limited privileges. This will generally lead to failures unless the MSI does not write to machine-wide resources (i.e., doesn’t to “c:\Program Files\ISI”).
Issues with Custom Actions running “Per-User”
When running a “Per-User” installation, having the Custom Action set as “deferred in system context” actions will run in the same context as normal deferred or immediate custom actions, which is with user impersonation. This can potentially cause a runtime issue with the custom action in the following circumstances:
- The user that launched the MSI installation is not an administrator, or is running on Windows Vista, in which users are part of the administrators group, but do not have administrator privileges by default.
- The custom action attempts to modify a resource in a “Per-Machine” location on the machine, such as a file in Program Files, or a registry key/value in HKEY_LOCAL_MACHINE in the registry.
While this may not be an issue with Windows XP or older versions of Windows, Windows Vista/Win7 does not run users with full administrator privileges by default. Therefore, since a “deferred in system context” action runs with user impersonation when ALLUSERS is not set, the custom action could fail.
The recommendation to prevent this issue arising is to ensure that a “Per-Machine” installation is always performed by setting ALLUSERS to 1 in the Property Table or on the command line. Per-machine installations are generally easier to manage, and are the current best practice recommendation from Microsoft.
For further research, please refer to my reference documents: