Sometimes, installed MSIs fail to uninstall. There can be various reasons, but one of the most common ones is when a custom action fails.
'Error 1720: There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor.
This could happen because the target script/exe is missing, or because the custom action script has an error in it, or due to a missing condition (maybe the custom action only had to run during the installation). What’s relevant is that the MSI will always try to run that custom action and probably fail.
The solution to this issue is editing the MSI and fixing the issue (disabling the custom action for uninstall, for example), and then re-caching it. This way, Windows Installer will use the new version. It’s important that the elements used for identification remain the same: ProductCode, PackageCode, ProductVersion and so on.
To re-cache an MSI, one might want to use the command line:
msiexec /fv "path_to_msi" <optional parameters>
However, the script below takes this further and goes through the following logic:
– It reads MSI info from the MSI file (ProductCode, PackageCode)
– It checks if a product with the corresponding ProductCode is installed
– If Yes, it retrieves the PackageCode and if it’s the same as the one we’re trying to re-cache, then it actually re-caches the MSI
'Logic: 'The Script retrieves the PackageCode and ProductCode from the MSI file, then it searches (by ProductCode). 'If the Product IS installed and the PackageCode is THE SAME, it recaches the MSI Option Explicit Const ERR_NOTFOUND = 2605 Const ERR_MSI = 2603 'general MSI io/query failure Const ERR_DIFPACKAGE = 3000 'Create Objects, declare variables dim installer dim strProductCodeIn, strPackageCodeFound, strMsiFilePath, strLogFile, strPackageCodeIn dim retCode, verFound, bStatus retCode = 1 strMsiFilePath = wscript.arguments(0) strProductCodeIn = GetMsiProperty(strMsiFilePath, "ProductCode") strPackageCodeIn = GetMsiPackageCode(strMsiFilePath) strLogFile = wscript.arguments(1) If strProductCodeIn = "" Or strPackageCodeIn = "" Then wscript.quit(ERR_MSI) ' Check if Product Is Installed, by Checking PC On error resume next Set installer = Wscript.CreateObject("WindowsInstaller.Installer") strPackageCodeFound = installer.ProductInfo(strProductCodeIn,"PackageCode") On error Goto 0 If strPackageCodeFound = "" then bStatus = False retCode = ERR_NOTFOUND ElseIf strPackageCodeFound = strPackageCodeIn Then bStatus = True ' present dim strCmd, shell Set shell = CreateObject("Wscript.Shell") strCmd = "msiexec /fv " & Chr(34) & strMsiFilePath & Chr(34) & " /norestart /qn REBOOT=ReallySuppress /L*v " & Chr(34) & strLogFile & Chr(34) retCode = shell.Run(strCmd, 0, True) Else 'ProductCode foundversion found but cannot be replaced. retCode = ERR_DIFPACKAGE End If Set installer = Nothing wscript.quit retCode
Please feel free to use the script.
The extra functions can be found on the corresponding articles, here:
The exit codes of the script can be customized, of course.