wix: ICE57 and ICE91 warnings for perUser installer - wix

I'm using wix 3.5 to author a windows installer with the "perUser" install scope. The wxs file is here, the resulting MSI file is here.
I get the following strange warnings from the light.exe linker. I'm not sure if I should just suppress them or if there is some better way to fix this.
ICE57
D:\hg\downmarker\setup\product.wxs(34)
: warning LGHT1076 : ICE57: Component
'component.downmarker.exe' has both
per-user and per-machine data with an
HKCU Registry KeyPath.
This warning doesn't make sense to me, because the installer works fine without administrative access - which AFAIK proves that the installer doesn't write any "per-machine data" as the warning claims.
ICE91
D:\hg\downmarker\setup\product.wxs(37)
: warning LGHT1076 : ICE91: The file
'downmarker.exe' will be installed to
the per user directory
'DownMarkerFolder' that doesn't vary
based on ALLUSERS value. This file
won't be copied to each user's profile
even if a per machine installation is
desired.
This warning doesn't make sense to me either because I explicitly mark the installer as having the "perUser" install scope.

ICE57 is shown because component "component.downmarker.exe" contains registry entries from HKEY_CURRENT_USER and HKEY_CLASSES_ROOT. HKEY_CLASSES_ROOT is per-machine, so the component has both per-user and per-machine data.
I noticed you are using HKEY_CLASSES_ROOT for a file association. You can use "HKEY_CURRENT_USER\SOFTWARE\Classes" instead to obtain a per-user file association.
ICE91 is harmless and can be ignored for per-user installations:
http://msdn.microsoft.com/en-us/library/aa369053(VS.85).aspx

Related

Wix msi updated property value not working during installation

Working with Wix in Visual Studio. I have a public property defined in Product node of wxs file.
<Property Id="MYPROP" Value="123456789"/>
The property value is passed as commandline argument to a deferred custom action executable. I'm able to receive it in the exe as well. The problem is even if I update the Property using vbs (verified through vbs select as well), when I launch the msi, it still passes the default/original value (123456789) to the custom action executable.
Also tried msiexec.exe /i myinstaller.msi MYPROP=SomeOtherValue
I'm still seeing the original value. What's wrong?
Maybe try this simple thing first:
<Property Id="MYPROP" Secure="yes" Value="123456789"/>
Essentially you need to add a property to the SecureCustomProperties list to have them pass properly to deferred mode in secure desktop environments.
See more information on SecureCustomProperties here. The technical details here are a little bit in flux because of Windows changes, so please just try this first - there could be several other reasons.
How do you use this property? What does it do?
When an msi is run, windows caches the msi file in %windows%\Installer folder. When that msi is run again, windows checks if an msi with identical PackageCode exists in the cache, if so then it uses the cached msi file instead.
PackageCode: identifies each unqiue msi installer package - even if it only has different properties.
In short, when a property is updated using a vbscript etc, then the PackageCode has to be updated as well. This will ensure that after updating msi, the same msi can be used on the same system and windows will not use the cached msi.

Why does MSI installer succeed when chosen component was not installed?

I have an MSI installer package that enforces the user to choose from a list of possible components to install, like "Version 2018" / "Version 2019" / "Version 2020". The chosen components will install themselves in a folder inside "ProgramData" that is usually writeable by every Administrator account on the system. However, in a recent customer support, this folder was created by the SYSTEM account. Probably the customer's IT installed the environment with SYSTEM privileges.
When the installer tries to put files into this folder it obviously fails. The problem is that the installer notices the missing permission, but still succeeds.
Is there any way to enforce MSI installer to abort / throw an error when a user-chosen component (or any other essential component) could not be installed?
What you want should be the default behavior of WiX / MSI as noted below. It's hard to say what's going on without a logfile.
Take a look at the WiX File#Vital attribute: https://wixtoolset.org/documentation/manual/v3/xsd/wix/file.html
If a file is vital, then installation cannot proceed unless the file
is successfully installed. The user will have no option to ignore an
error installing this file. If an error occurs, they can merely retry
to install the file or abort the installation. The default is "yes,"
unless the -sfdvital switch (candle.exe) or SuppressFileDefaultVital
property (.wixproj) is used.
It sets the underlying msidbFileAttributesVital bitmask in the Windows Installer File table as documented at:
https://learn.microsoft.com/en-us/windows/win32/msi/file-table
The file is vital for the accurate operation of the component to which
it belongs. If the installation of a file with the
msidbFileAttributesVital attribute fails, the installation stops and
is rolled back. In this case, the Installer displays a dialog box
without an Ignore button. If this attribute is not set, and the
installation of the file fails, the Installer displays a dialog box
with an Ignore button. In this case, the user can choose to ignore the
failure to install the file and continue.

WiX repair from managed bootstrapper fails to fix some corrupted DLLs

I have a WiX Managed Bootstrapper Application that installs some MSIs. I also have a series of tests that exercise the various functions of the installer. The problem I'm having is with the repair test. The test purposely corrupts all the DLLs we install then calls the EXE installer with "/repair /passive" flags. Once completed around 80% of the DLLs are repaired but the remaining ones are untouched and therefore still corrupted after the repair.
If I manually run msiexec on an individual MSI with the command line args "/fa" which instructs the MSI to forcibly replace all the files it installed, it fixes 100% of the DLLs.
My question is how can I force the MBA to instruct each MSI to repair in this way? I've tried setting the REINSTALLMODE property to 'amus' on the individual MSIs in their .wxs files but the MBA overwrites them at run time as is evident in the log via this line:
PROPERTY CHANGE: Modifying REINSTALLMODE property. Its current value is 'amus'. Its new value: 'cmuse'.
I've also tried to set the properties in the MBA to pass through to each MSI but it doesn't appear to pass them and instead uses it's default values.
I see many similar questions here but none actually address this specific issue. Any help would be greatly appreciated. Rob save me!
Here's your problem right here:
[12:25:25:874]: File: C:****\estimator.dll; Won't Overwrite; Won't patch; Existing file is unversioned but modified
The installer doesn't want to overwrite a file that has changed since it was installed if it cannot verify the version or language (and maybe some other properties?). Without these properties, it decides to look at the modified date. If it is newer than when it was first installed then it won't touch it assuming instead that something changed for a reason and reverting it will cause something to fail. (You can read more here)
One thing you can do in this case is use a Companion File
Set this attribute to make this file a companion child of another file. The installation state of a companion file depends not on its own file versioning information, but on the versioning of its companion parent. A file that is the key path for its component can not be a companion file (that means this attribute cannot be set if KeyPath="yes" for this file). The Version attribute cannot be set along with this attribute since companion files are not installed based on their own version.
Basically you will set the logic for installing/uninstalling this component to be the same as the "FileID" of another component in the install. In the estimator.dll component, in the File tag, remove KeyPath="yes" and instead replace that with CompanionFile="<NameOfAnotherFileID>".
The issue with this approach is that you may have a corrupted DLL but the companionFile it was linked to was fine so it is not reinstalled.
If this is a dll you do own, I would highly suggest versioning the file! Give it any version you want and this issue should go away.
Another thing you can try, although I don't know how it works really, is giving the file a DefaultVersion
This is the default version of this file. The linker will replace this value from the value in the file if the suppress files option is not used.
This would be the quickest solution to verify. Just build a new installer with DefaultVersion="1.0" in the estimator.dll's <File> and see if it gets replaced. I think this will have the installer think the file is versioned 1.0 but the installed file is not versioned so it will replace it (see here)

Change install path of MSI setup while repairing

I am trying to repair an installed msi setup with below argument:
msiexec /f "msipath"
It is repairing properly. But while repairing i need to change its install path too. I tried this argument msiexec /f "msipath" INSTALLDIR="path"
But this is not working.
Whether it is possible to change the install path of an msi while repairing it?. If possible means, please share the exact argument.
It is not possible. For a component to be moved, it must be uninstalled and then reinstalled. (Repair just replaces resources in their original locations.) Consider this note on MsiSetTargetPath:
Do not attempt to configure the target path if the components using those paths are already installed for the current user or for a different user. Check the ProductState property before calling MsiSetTargetPath to determine if the product containing this component is installed.
Thus you typically have to remove and reinstall the entire package. A major upgrade can be a good way to accomplish that, depending on your other needs.

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