How to make a setup work for limited (non-admin) users

I believe I have found the answer on this page:

Link


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.


NOTE: Step 5 can be done using Orca, Microsoft's MSI editing tool. Open the MSI file in Orca, select View-->Summary Information... then check the "UAC Compliant" checkbox.

NOTE #2: Step 5 can be done using the WiSumInf.vbs sample script file included in the Microsoft SDK: C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\sysmgmt\msi\scripts\WiSumInf.vbs

NOTE #3: Step 1 seems to be taken care of in a Visual Studio Step Project by right-clicking on the setup project, choosing View-->User Interface, getting properties for the "Install/Start/Installation Folder" page and setting "InstallAllUsersVisible" to False.

NOTE #4: Yet another way to do Step 5, use the MsiInfo.exe tool included in the "Windows SDK Components for Windows Installer Developers" http://msdn.microsoft.com/en-us/library/aa370310(VS.85).aspx

Addition to the NOTE #4: Assuming that you are using long file names and compressed media (default behavior for an MSI) the PostBuildEvent command would be something like:

"C:\Program Files (x86)\Windows Kits\8.1\bin\x86\MsiInfo.exe" "$(BuiltOuputPath)" /w 10

Note that you will have to change the path to the MsiInfo to match the one that it has in your system.


For Visual Studio v2017 with Visual Studio ​Installer Projects v0.9.1:
This solution requires a commandline tool that is installed as part of the Windows SDK

  1. In Visual Studio: select the Visual Studio Installer project in Solution Explorer.
    Press the F4 key to see the project properties
    Set InstallAllUsers to false

  2. Right click the project in Solution Explorer > View > File System
    Select Application Folder. (right click > Properties Window)
    Change [ProgramFilesFolder] to [LocalAppDataFolder]

  3. Build the MSI
    (Right click the project in Solution Explorer > Build)

  4. Open a command prompt or add a postbuild event to run the Windows SDK utility msiinfo.exe - example:
    "C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\MsiInfo.exe" "c:\yourprogram\installer.msi" -w 10

Notes: The msiinfo.exe -w 10 switch sets the MSI "Word Count Summary" property of the MSI file to "compressed - elevated privileges are not required to install this package". More info here