I am a huge fan of the open source WiX Toolset1 for authoring Windows installers. I’ve used Installshield and Visual Studio Setup projects for installers past. I even had to reverse engineer an old VB Package and Deployment Wizard installer for a customer. It only took me 16 hours to re-author it with WiX (and that included testing). Sure, sometimes it would be nice to have a GUI for spitting out the XML, but with the control WiX offers me there’s no going back. If you’ve never experienced the power of WiX (including custom actions in C#), you are missing out!
This week I ran into a situation where I needed to do something that I didn’t think would be so hard to figure out.
- I really needed a per-user install.
- I really needed the installer to prompt for elevation.
I wanted a per-user install so that the application is only visible in Add/Remove Programs for the user who installed it. And my installer performed custom actions which required elevation and I didn’t want to require my users to launch the MSI with msiexec
from a command line with elevated privileges. Turns out that most people are looking for the opposite–a per-user install that doesn’t prompt for elevation, like this excellent post details. So according to those instructions, I figured I would just leave ALLUSERS undefined and then set the opposite InstallPrivileges attribute, namely Package/@InstallPrivileges="elevated"
(and Package/@InstallScope="perUser"
for good measure).
With those settings, running my installer from a standard user account without admin rights was not prompting for elevation and my installer was failing. Crap. Back to Googleing, it was surprising how many posts like this one I found which were answered only by saying that per-user installs should never require elevation. That may very well be the case, but I have a legitimate need to do this. Luckily, I found a post2 that offered the clue I needed: Package/@InstallScope
doesn’t support per-user, elevated packages!
All I had to do was omit the Package/@InstallPrivileges
(defaults to elevated) and Package/@InstallScope
attributes (continuing to leave ALLUSERS undefined). I also incorporated the trick I found from the MSDN blog above to prevent a user from setting ALLUSERS from an msiexec command line install.
There you go, problem solved.