WiX - Elevating (or reducing) privileges at install time - wix

I am working on a project that has been using 2 VD projects to distribute admin and user versions of installations, and now I need to switch to WiX. It was a bit painful experience with lack of documentation and all, but I managed to make something of it.
However, there is still one problem: I want to make only one .msi which will allow user to choose whether he wants to install as admin or as user. If he chose user, I don't want to ask him for elevation (as he doesn't need it), also if he chose admin, I don't want the installation to crash but to ask for privileges.
My current solution crashes in admin mode if I set InstallPrivileges to limited because the user doesn't have the permission to install, and it prompts for elevation in user mode if I set it to elevated.
My opinion is that there is no way to fix this because of compatibility with MSI, but perhaps there is some way to change privileges from elevated to limited in install time that I'm missing.
In conclusion, I want to know these things:
Is it possible to change privileges at install time
If there is no way to do so, what is the best workaround for this problem (exporting 2 .msi files or something)

One solution is to build two separate installers and then launch them via a custom WiX bootstrapper (aka Burn). The bootstrapper would be in charge of displaying the UI and launching the appropriate .msi.
Or you could separate the "admin" features into a separate .msi and then use a custom bootstrapper to install both .msis if the user selects an admin install.

Related

Wix Bootstrapper manifest or elevated custom action

I know that this is a topic that has been discussed many times and people always claim: Wix bootstrappers should not require to be run elevated. Let me explain our requirement and hopefully anybody can suggest a solution that will work on all systems.
Our installed software is a Windows Service which runs elevated. The service has various settings which are stored in a database that can only be accessed by administrators. The installer also allows the configuration of those settings which is done as part of the elevated phase of the installer. And here is the problem: We cannot load the current settings from the database within the unelevated phase of the bootstrapper.
The easiest solution would be to run the whole boostrapper elevated but it seems that Wix intensively tries to prevent elevated bootstrappers by design. All discussions in this area result in wierd solutions where external tools are used afterwards to embed an application manifest after the Wix compilation.
Yes in theory we could rework the whole database credentials in order to allow the installer read access but I would like to prevent this due to security reasons. We could also keep a copy of the settings for the installer on a readable location (e.g. registry) but this is also not nice to maintain.
Is there some clean Wix-built-in mechanism to load those settings or elevate the bootstrapper from the beginning using an application manifest? We are aware that elevated bootstrappers are "not nice" to the user but our software addresses service operators that anyhow must have administrator privileges in order to operate our software.
Update #1: We already have a custom WPF-GUI as bootstrapper application utilizing the Microsoft.Tools.WindowsInstallerXml.Bootstrapper.BootstrapperApplication class provided by Wix.
If it's not necessary for the UI itself to be elevated you can force the install engine to elevate so all the bootstrapper packages will be installed\executed in an elevated mode.
To elevate the engine use the Elevate method of the Engine (the Elevate gets a 'IntPtr hwndParent' parameter - I've used the IntPtr of the window and it worked great).
(Calling the Elevate method will show\pop the UAC elevation screen)
Just keep in mind that the Elevate method is not a blocking operation and from I remember it always returns true. The only way (that I've found) to determine if the elevation actually succeeded is to register to the bootstrapper's Error event and check if the error type is ErrorType.Elevate.
Keep in mind that in this solution the UI itself will remain un-elevated.

Having an issue with WIX upgrade

Having an issue with WIX installer upgrade. Previously we had 2 version of installers 1 for per-machine and another for per-user.
Currently we have developed a dual mode MSI.
The dual mode MSI upgrades the PerUser version (on PC 1) of previous installer when install for yourself option is selected but when install for all (on PC 2 ) is selected it install a new product
Is it some wrong that we are doing or is have to set some properties. We are using WIX.
Please help
Per-user installs allow the installation of the same product multiple times for different users - and in different versions too. This makes upgrades and patches rather difficult to deal with, and I dislike this per-user concept altogether. I prefer to set the installer per-machine as standard. I don't feel that much is lost in functionality, but a lot is gained in managability. Though this is not an answer to your question, it is worth pointing out that per-user installs is a flawed concept - at best.
I don't know if it is an option to set your installer per-machine, but I found a way to migrate installs from per-user to per-machine automagically by using Installshield and its custom ISSetAllUsers custom action. The procedure is described here:
windows Installer - uninstalling previous version when the versions differ in installation policy (per-user, per-machine)
Wix does not feature such a custom action as far as I know, but you could write your own custom action using the Win32 API call ::MsiEnumRelatedProducts() as described by Rob Mensching here: how to change from per user to all user installation?
Here is a similar post for reference: How can a perUser installation program deal with a perMachine older version of the program?
Here is a blog describing (further) issues with per-user installs: Understanding “Per-User” or “Per-Machine” context for application Setup packages.
Let me add a couple of further comments:
You can have per-user settings without a per-user install. This is no problem, just have the application set up the userprofile on launch. I prefer to install all resource files and settings per-machine and have the application copy them to each user for first launch initialization. This ensures that user settings are not entangled with your MSI at all.
It is rare to maintain two separate versions of the same product at the same time - hence users are all likely to use the same version of the product. Per-user is just more headache in this perspective.
The upgrade and patching logic involved in per-user installer scenarios beats me - it just doesn't make any sense to me. If there is a per-machine install already, does a per-user install make sense to you? Does this install the application one more time?
If per-user installs are still important, perhaps you can try ClickOnce (if it still works). Quote from Wikipedia: "...ClickOnce-deployed applications are considered 'low impact', in that they are installed per-user, not per-machine. No administrator privileges are required to install one of these applications. Each ClickOnce application is isolated from the others. This means one ClickOnce application is not able to 'break' another.". Per-user installs make more sense if they are hooked up to auto-updating and web-deployment.
If you had two setups before, it might be that you have two upgrade code and need to deal with both for the upgrade to work in all cases?
It has been a long time since I dealt with per-user stuff, but in general you must author your Upgrade table to include both upgrade codes for your setups to detect all flavours of your previous install. The upgrade table allows you to detect any number of prior installs that should be scheduled for uninstall before your new product gets installed.
The FindRelatedProducts MSI action will search all packages on the target machine in order to find any where the Upgrade Code property matches the value specified in the upgrade table.
Make a verbose log file as has been suggested:
msiexec.exe /I "File.msi" /QN /L*V "C:\Temp\msilog.log"
/I = run installation sequence
/L*V "C:\Temp\msilog.log"= verbose logging
/QN = run completely silently
I believe this is occurring because in your installer the default mode is Per-User hence it is not detecting per-machine.
You could use MSIGetProductInfo to find the installed products if the assignmenttype is “1” then you could set the below properties to Product Code of Per-Machine product
WIX_UPGRADE_DETECTED
OLDERVERSIONBEINGUPGRADED
Use a custom action on button click or schedule it after FindRelatedProducts.
This tells the installer of an existing version and installation is handle like an upgrade.
Windows Installer does not upgrade between per user and per machine, or vice versa. If you want this to happen you need to get in front of the install somehow and find out what type is already installed. Trying to do that when the product has been installed for another user (i.e. not the current installing user) is tricky. MsiEnumRelatedProuctsEx can be called a couple of times looking for per machine and per user installs to see what's going on. However there may be issues with you, User A, trying to uninstall a product that was installed per user by User B. If you are the same user it's easier. MsiEnumRelatedProductsEx can be called a couple of times to see if the product is per user or machine (in a launcher maybe) and you can uninstall the product before installing the new upgrade, or at least tell the user to do the uninstall. Anyway, it can be a mess, and the advice to stick with per machine installs is worth taking.
I should also point out that allowing per user AND per machine installs on the same machine is a feature, not a bug.

Are there any requirements for .msi and .exe installers for SCCM?

I have a small application that is designed to run under currently logged on, non-administrative workstation user. Application can be installed manually but I also made sure that it is compatible with Group Policy Objects (GPO) software distribution method - I have .msi files for old systems (XP/Vista): separate files for per machine and per user installations as well as .msi file that takes advantage of Windows 7 (and newer) compatibility with WIX Allusers=2 option to allow automatic registry and folder path redirection depending on the installation context.
All is good there, but I am just wondering, is there anything special I need to do to make my installer suitable for installation using Microsoft System Center Configuration Manager? I do not really have resources to just test such a scenario myself and would like to find out about theoretical requirements for installer files for SCCM.
At my day job I'm the Deployment Architect for a Fortune 50 company with an SCCM 2007 environment ( currently migrating to SCCM 2012 ) that has over 300,000 clients. Here's a few tips.
1) We don't do Per-User installs. They are impossible to manage and report on. If an installer must have Per-User resources and we can't get the application (typically vendor provided) we do this using an Active Setup technique where the first time each user logs on the MSI does a repair and populates the Per-User resources. Just realize you'll never get it off... it's essentially forever.
2) SCCM can handle non MSI deployment types but well written MSI's work the best.
3) Use snapshotted VM's to test your install in the SYSTEM context. (PSExec is your friend)
4) Test your install, uninstall, reinstall, upgrade, repair, change. Make sure everything is bulletproof.
5) Don't wrap up prereqs into a setup.exe bootstrapper. Decompose it and allow SCCM to package each of these items. You can then use package chains, task sequences or application model to allow SCCM to manage the chaining. You get better status, reporting and efficient use of the system.
Just a couple of thoughts if I remember these things correctly - the MSI should be capable of silent install, and among other things that means no custom actions exclusively in the UI sequence, because they will not be run at deployment time because you will probably suppress the UI. The execute sequence shouldn't have custom actions that might explicitly display messageboxes requiring acknowledgement unless they are based on calls to the Win32 MsiProcessMessage() API or equivalent.

Privileges for installing executables with nsis

I need to write an installer for some executables. The user might copy them wherever he wants but usually this is performed in C:\Program Files\MyProgram
If there's visual studio installed I also need to copy something to system32 (and that requires admin rights I suppose).
Does that make sense to support normal users and admin users? I mean: if I need to install something I always need admin rights, is this correct?
Supporting both can be tricky but it can be done by using RequestExecutionLevel highest and then checking if you actually are admin with the UserInfo plugin. You would then have to tell the user to force the installer to run as admin if they are not already when you detect VS.
A normal user cannot write to $programfiles so you have to default $instdir to $localappdata\Programs\Yourapp. You should also take a look at SetShellVarContext, it will help you with the HKCU vs HKLM issue...

Installation change do not ask for UAC permissions

I implemented an installer for our product. Installer needs administrator privileges, so I used setup bootstrapper with a manifest file (as recommended here) to get these privileges on a Windows machines with UAC enabled. Installation and uninstall goes fine - the user is asked for permission and the installer does what it needs to do.
But if you run Control panel → Programs and Features and select "Change"* for installed program, an error occurs (custom, from installer LaunchConditions), telling that the installer needs administrative privileges. And I can't find any way to ask for permission in a such case - Windows simply runs the MSI file and doesn't know anything about required permissions.
Even more strange is the repair functionality - it asks for permission, but then fails to do some actions that were allowed during installation, using SetupBootstrapper.
I found a similar problem here:
But the proposed solutions are unacceptable in our case.
The only workaround for the change functionality now is to always use SetupBootstrapper and do not use the Programs and Features menu, but that is not very user-friendly and forces the user to keep the installer on his/her hard drive.
Has anybody better advise?
PS: I use WiX for creating the installer, so it would be great to hear about WiX solutions, but I'm pretty sure that it doesn't depend on the installer creation language, but only on MSI specifics.
What actions are failing? If they are actions that you added to the installation, make sure that such actions are defined with Impersonate="no" and Execute="deferred" (or "commit" or "rollback") and that they are sequenced somewhere between InstallInitialize and InstallFinalize.