Write to local machine registry in custom action (conditionally) - wix

Windows Installer has the smart feature to automatically decide whether to store registry values under HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE (using Root="HKMU" in WiX).
I need to write some complex registry keys during installation so I created a custom action for this. Depending on whether ALLUSERS is set or not HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE will be the location that is used by the custom action.
Unfortunately, I had to realize that even in an ALLUSERS installation the custom action does not have the required privilege to write to HKEY_LOCAL_MACHINE unless the installation is started as administrator. How do I get the custom action to write to HKEY_LOCAL_MACHINE but still keep the option of a per-user install?

Don't use a custom action, you'll lose all the other smart features of Windows Installer such as ugprades, rollbacks, uninstalls and so on.
Instead, put the registry values in their own component and put a condition on the component. If the condition evaluates to true the component and it's associated registry resources will get installed.
Take a look at the Privileged property. It sounds like what you are looking for to do your evaluation.

Related

WIX/MSI setup writes to HKLM despite MSIINSTALLPERUSER=1

I try to create a MSI Single Package using WIX (3.10). The user can select in the UI whether the package should install Per-User or Per-Machine. The package is initialized with ALLUSERS=2 and MSIINSTALLPERUSER=1. I did not set an InstallScope, as this would limit the Package to one or the other.
If the user selects Per-Machine the setup continues with ALLUSERS=2 and MSIINSTALLPERUSER="". - Everything works as expected.
If the user chooses Per-User installation ALLUSERS=2 and MSIINSTALLPERUSER=1 remain unchanged. If a non-privileged user runs the setup everything works as expected as well.
But if a privileged user executes the setup and chooses Per-User installation, registry keys that should be written to HKCU\Software\Classes\ are still written to HKCR / HKLM\Software\Classes\. This happens without UAC being invoked.
I observed this behavior on a Windows 8.1 (current patch level).
This is not what I want. If the user selects Per-User installation, there should be nothing written to HKLM/HKCR.
Here is sample from the wxs-file:
<Component Id="MyRegistryComponent" Guid="{99999999-9999-9999-9999-999999999999}">
<RegistryValue Id="MyRegistryComponent_MainKey" Root="HKCU" Key="Software\Classes\myapp.myclass" Value="myapp.myclass.foo" Type="string" />
</Component>
I checked the MSI with Orca. This RegistryValue has Root=1 in the Registry table of the MSI.
I tried/checked already:
I verified that the ALLUSERS and MSIINSTALLPERUSER properties are
indeed set as stated above.
I tried setting ALLUSERS="" MSIINSTALLPERUSER=1 – No effect.
I changed Root="HKCU" to Root="HKMU" in the wxs.
This results in Root=-1 in the MSI, but I does not change the final
result after installation.
What am I missing here?
Is possible that this behavior is caused by previous incomplete (un-)installations?
When you say "This results in Root=-1 in the MSI, but I does not change the final result after installation." it's not clear which of the results you're referring to but:
HKCU will always go to HKCU, HKMU is what you need to switch between HKCU and HKLM in a single package setup. So using HKMU and producing a verbose log would be useful to see if there is a failure somewhere in there.
You will get changes in HKCR. That's usually the normal behavior because as this article explains:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx
Quote "The HKEY_LOCAL_MACHINE\Software\Classes key contains default settings that can apply to all users on the local computer. The HKEY_CURRENT_USER\Software\Classes key contains settings that apply only to the interactive user. The HKEY_CLASSES_ROOT key provides a view of the registry that merges the information from these two sources. HKEY_CLASSES_ROOT also provides this merged view for applications designed for previous versions of Windows."
HKCR is a virtual view that combines class registration for the current user with class registration for the machine to present a view of all class entries on the system. Other accounts (such as the system account) will see only HKLM, so what you see exactly depends on who you are.
I suggest that is what is needed here is a test case that uses HKMU as is required, and maybe post that test case. Keep in mind that seeing HKCR entries is normal, going by the documentation, so maybe that explains all that you are seeing.

Wix Installer: Write to HKLM/HKCR in per-user installation without elevated rights

I created a "perMachine" installer with the wix toolset. The installer has to be started with admin rights, because it writes multiple registry keys to HKLM and HKCR.
I'd like to change the installer to a "perUser" installation. Is it possible to do this and still write to HKLM and HKCR? The registry entries have to be there to register a shell icon overlay handler...
Greets
EDIT:
There does not seem to be a way to write to HKLM as non-admin user.
But is there a way to get wix installer to promt for admin pw? If so, I could live with the following solution:
user knows admin pw (or admin provides pw): the icon overlay component is installed
user does not provide admin pw: the icon overlay component is skipped.
So my questions are:
1. How to promt the user for the admin pw?
2. How to skip/install a component based on the users action?
EDIT2:
I have tried multiple combinations of:
InstallPrivileges="elevated"
InstallScope="perUser"
Property "ALLUSERS" set to empty string
Property "MSIUSEREALADMINDETECTION" set to 1
Property "MSIINSTALLPERUSER" set to 1
Condition for said component: "Privileged / AdminUser"
Nothing has worked so far. It all comes down to the Condition not beeing read correctly. I have tried on several PCs with an admin user. In order to get the product to install with ALL features, I have to start the installer explicitly as administrator over the context menu. Otherwise the icon overlay handler won't get installed.
Pointing out something that the OP doesn't seem to understand fully...
Per machine and per user have nothing to do with the privilege required to write to HKLM. Windows Installer won't break security rules either way. If the install requires privilege and doesn't have it, then it fails in both cases. In WiX, the Package InstallPrivileges is what tell Windows whether to elevate so that the install will work. If the installing user doesn't have the privilege the elevation prompt will allow entry of admin credentials. So the answer to your 1 is that InstallPrivileges=elevated should allow entry of an admin account if the user is not admin. otherwise a plain elevation.
You could try a condition on the components containing the restricted registry entries, try a condition of Privileged so they install only if the install is elevated. I have never tried this, but it should work.
https://msdn.microsoft.com/en-us/library/aa370852(v=vs.85).aspx
Other alternatives are:
Group Policy will allow the setup to be pushed to machines of limited users. This is common in corporate environments.
It occurs to me that the shell icon overlay function might be available on a user by user basis. This is a SWAG, and I'm not aware of all the registry entries required, but you can certainly register your COM classes in HKCU, for example. If you use the WiX HKMU key, the items will be created for the machine in a per machine and for the user in a per user. An example here:
http://www.merlinia.com/mdt/WiXTutorial1.msl
No, a per-user install has write-access to only per-user resources like the registry and c:\users when configured for per-user. This has the effect in Vista and later of not requiring elevation and thus not requiring UAC.

wix pass option to msi for repair

When I repair using the msi, a registry entry is properly re-created. When using the exe generated by Burn, the entry is not-recreated, unless the exe associated with the reg entry also requires compare.
I wonder if, when burn invokes msi, if it is overriding the default /fm behavior of msiexec.
That switch means "repair all required computer-specific registry entries "
Is there any way I can confirm, deny, or modify that behavior?
When planning a "Repair" operation in Burn the REINSTALLMODE is "cmuse". For a "Modify" operation the REINSTALLMODE is "cmuso". So "m" is present in both cases.
The Burn log file should say, "Planning action: Action" and that will tell you which it is doing. If you are executing a Repair operation and there is not newer version of the executable on the machine than what your MSI expects, Burn's REINSTALLMODE should work. If you are doing a "Repair", look in the generated MSI log file for the same Burn execution and see what the Component states are for the Components that are not repaired. That should help you track back to see why the Component was not fixed.
From the provided log file:
Command Line: ARPSYSTEMCOMPONENT=1 MSIFASTINSTALL=7 REINSTALLMODE=cmuse
REBOOT=ReallySuppress IGNOREDEPENDENCIES=ALL CURRENTDIRECTORY=C:\temp
CLIENTUILEVEL=3 MSICLIENTUSESEXTERNALUI=1
The lack of REINSTALL=ALL shows that EnableFeatureSelection='yes'. Either remove that attribute (or change it to the default 'no') or your BA needs to handle the OnPlanMsiFeature() callback

Schedule a Reboot if there is a change in file version

I have a MSI package, which installs a Driver, however the Uninstall of the driver require a Reboot. for which I had scheduled a Standard Custom Actions (scheduleReboot) after InstallFinilize, which works fine.
Now I would like to Schedule reboot only if I am replacing the "driver" file. is there any way of determining "Installed file version" and the "to be installed file version" and based on compassion, if there is a change, schedule reboot.
In some cases the Windows Installer can determine whether a system restart is necessary. For example, the ScheduleReboot action can be used to force the installer to prompt for a restart after installing drivers that require a restart. If the installer attempts to replace files that are in use, it automatically prompts the user to restart even if ScheduleReboot has not been used. The ForceReboot action must always be used with a conditional statement such that the installer triggers a restart only when necessary. For example, a restart may only be required if a particular file is replaced or a particular component is installed.
Each product installation is unique and a custom action may be required to determine whether a restart is needed. There are tables in the Windows installer database which you and use for Searching for Existing Applications, Files, Registry Entries or .ini File Entries and to set a property.
Note: When Replacing Existing Files, Windows Installer determines whether the component's key file is already installed before attempting to install the files of any component. If the installer finds a file with the same name as the component's key file installed in the target location, it compares the version, date, and language of the two key files and uses file versioning rules to determine whether to install the component provided by the package. If the installer determines it needs to replace the component base upon the key file, then it uses the file versioning rules on each installed file to determine whether to replace the file.

How can I execute a Custom Action as System user with Wix 3.0, before checking to see if files are in use?

So I have a Wix 3.0 project that installs an IIS7 Native Code Module. When uninstalling I would like to be able to shut down the IIS7 application pools before deleting the file so that a reboot is not necessary.
I am using the appcmd utility to shut down the app pools in a CustomAction element, but when I attempt to do an uninstall I get this error before the customaction is ever invoked:
The setup must update files or
services that cannot be updated while
the system is running. If you choose
to continue, a reboot will be required
to complete the setup.
I have the "After='InstallInitialize'" property set on the CustomAction, because the documentation says that any deferred/not-impersonated custom action must come between InstallInitialize and InstallFinalize.
So is there some way to have a custom action execute before this check for files in use is made? Or disable this check for a given file, or make the check happen later in the sequence?
Yes, you can specify the order for actions to occur by modifying the Sequence column in the InstallExecuteSequence table within the MSI file.
Get the ORCA tool to examine the MSI file to see what I mean, and use a Javascript script to modify the MSI as appropriate.