cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Lou_Elston
Level 6

Uninstalling multiple products in right order

Combined two installers into one (A and B are now combined into A). The B installer always needed to be uninstalled before the A installer could be uninstalled. If doing an upgrade using the new combined A installer, and B is installed, the B uninstall must be done first. I put the necessary records for both A and B into the Upgrade table. The problem is that the A uninstall kicks off first and the previous code for that product determines that B is still installed, it puts up an error message, and thus the uninstall and upgrade cannot continue.

Installshield support says that the order of what gets executed first in the upgrade table is arbitrary..is this true or does someone know differently?

Yes, I can create a custom action that does an uninstall of B and place it right before the 'RemoveExistingProducts'. The problem with this is that the user will have to respond to the "Are you sure that you want to uninstall this procuct?" message, (which does not say what the product is), and, there is no recovery if that uninstall goes bad.

Any ideas?
Labels (1)
0 Kudos
(3) Replies
Lou_Elston
Level 6

I am arguing against this, but I have been told to ask the question anyway.
What if, (programatically), we find the msi file belonging to the previously installed version of the installer and edit the condition on the custom action so that it does not object to the B product still being installed when we uninstall the A product (the check was put in because product B was dependent on product A and there would be no reason to still have it installed if product A was uninstalled). Then, if product A is selected for uninstallation first (being that there is no way to force it first in the Upgrade table), it will not fail and then product B should be selected to be uninstalled.

I have been taught to never touch the previous install msi file, so I would like to hear the opinions of others.
0 Kudos
MichaelU
Level 12 Flexeran
Level 12 Flexeran

I'd suggest avoiding it. Editing an MSI just before uninstall (while still not a great idea) is at least fairly safe against future patching problems, so it's probably among the least risky times to do it. However if you're considering doing this from a custom action in another MSI, consider that opening another MSI database from a custom action is generally not allowed, so its behavior is not guaranteed to continue to work as you might expect.

If you're doing this from a custom bootstrapper of sorts, I'd suggest just having that bootstrapper uninstall items in the correct order.
0 Kudos
Lou_Elston
Level 6

We ended up doing the custom action that is executed first when the next button is clicked on the Ready to Install dialog. This deletes the two records in the previous mis database and allows the uninstall of both products automatically, without the user having to respond to the "are you sure you want to do this" question, and I believe that the logging of both uninstalls is captured in the upgrade log file. this is the code...
-----------------------------------
Sub Modify20MSIFile()

'first find out what is the name of the installed XYZ msi file, and where it is located on the system

Dim strMsiLocation
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colSoftware = objWMIService.ExecQuery _
("Select * from Win32_Product Where Description = 'XYZ'")
For Each objSoftware in colSoftware
strMsiLocation = objSoftware.PackageCache
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ 2.0 msi file: " & strMsiLocation)
Next


'Delete the custom actions

Dim Database, View, Record, Installer
Set installer = CreateObject("WindowsInstaller.Installer")
Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1
Const msiViewModifyAssign = 3
Const msiTransformErrorNone = 0
Const msiTransformValidationNone = 0

'open the msi database
Set Database = Installer.OpenDatabase(strMsiLocation, _
msiOpenDatabaseModeTransact)

'create a view to delete from the InstallUISequence table
Set view = database.OpenView("Delete from InstallUISequence where Action = 'CheckProductBServer_Upgrade'")
If Err = 0 then
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallUISequence\CheckProductBServer_Upgrade was found")
else
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallUISequence\CheckProductBServer_Upgrade was NOT found")
end if
View.Execute
If Err = 0 then
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallUISequence\CheckProductBServer_Upgrade was deleted")
else
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallUISequence\CheckProductBServer_Upgrade was NOT deleted")
end if
View.Close

'create a view to delete from the InstallExecuteSequence table
Set view = database.OpenView("Delete from InstallExecuteSequence where Action = 'CheckProductBServerInstalled'")
If Err = 0 then
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallExecuteSequence\CheckProductBServerInstalled was found")
else
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallExecuteSequence\CheckProductBServerInstalled was NOT found")
end if
View.Execute
If Err = 0 then
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallExecuteSequence\CheckProductBServerInstalled was deleted")
else
WriteToInstallLog("+++ [CUSTOM_LOGGING] Modify20MSIFile +++ InstallExecuteISequence\CheckProductBServerInstalled was NOT deleted")
end if
View.Close

Database.Commit

end sub
0 Kudos