1. Introduction
I've got an MSI installer build via the WIX toolset.
This installer contains a dll library and a *.cab file that is used to install a 3rd party driver while installing my application. This process is done in the following steps: my MSI creates a directory in the INSTALLDIR
, then the driver is installed there by executing a deferred custom action from mentioned dll. I think that this pattern isn't really a valid one, but that's a side note.
During an upgrade, the directory where MSI installed a driver is removed. This causes issues when it's time to upgrade the driver as it must be done via another custom action defined in the dll library and those removed files must be present. Please notice: I cannot uninstall and install the driver during an upgrade, it's a limitation, unfortunately.
2. Workaround
The RemoveExistingProduct
was scheduled after InstallInitialize
.
As the driver's files mustn't be touched during an upgrade, as a workaround, I've changed RemoveExistingProduct
to be executed after InstallExecute
, so the files aren't firstly removed and then installed again, but rather overwritten if needed. I'm aware of how this affects the rollout procedures.
Question: Is this a proper/better way (as proper as a workaround can be...) of handling it? Can it cause some unwanted side-effects? So far I've observed in logs:
Disallowing uninstallation of component: {GUID-HERE} since another client exists
Another question: Is this expected?
3. Details and some XML
The Product ID
and Package ID
are always generated ("*"
). The UpgradeCode
remains the same between different versions. The REINSTALLMODE="omus"
.
The upgrade is done via <Upgrade>
element:
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect='no' Property='AUTO_FOUND_PREVIOUS'
Maximum='$(var.VersionNumber)' IncludeMaximum='no'
IgnoreRemoveFailure="yes" MigrateFeatures="yes" />
<UpgradeVersion OnlyDetect='no' Property='AUTO_FOUND_SELF'
Minimum='$(var.VersionNumber)' IncludeMinimum='yes'
Maximum='$(var.VersionNumber)' IncludeMaximum='yes'
IgnoreRemoveFailure="yes" MigrateFeatures="yes" />
<UpgradeVersion OnlyDetect='yes' Property='AUTO_FOUND_NEWER'
Minimum='$(var.VersionNumber)' IncludeMinimum='no' />
</Upgrade>
And as I mentioned, the directory where the driver is installed is also managed by my MSI:
<DirectoryRef Id='INSTALLDIR_DRIVER'>
<Component Id='cmp_driverPlaceholderDir' Guid='{CONST-GUID-HERE}'>
<CreateFolder />
<RemoveFolder Id='INSTALLDIR_DRIVER' On='uninstall' />
</Component>
</DirectoryRef>
Other components have also constant GUIDs.
I'd love to also hear how the installation of an external driver from custom action should be handled in the proper way, don't hesitate if you have some knowledge about it.