Uninstall software

My product has an auxiliary executable to remove all related products. I delete all subfiles based on update codes.

First, I extract the product code from the update code using the MsiEnumRelatedProducts function. Then I try to uninstall the product using the MsiConfigureProductEx function .

Problem MsiConfigureProductEx returns an error.

Function called: MsiConfigureProductsEx
Return Code: 1605 (0x00000645)
Description: This action only applies to products that are currently installed.

Why MsiEnumRelatedProducts return an invalid product code? I looked in the Windows registry to see if such a product code exists. No. How to debug a problem?

Edit: Added a minimal code that reproduces the problem.

 // UpgradeCodes is an array having upgrade codes of all modules. TCHAR lpProductCode[GUID_STR_LENGTH]; const TCHAR tszNoReboot[] = _T("REMOVE=ALL REBOOT=ReallySuppress DISABLE_REBOOT_PROMPT=1"); for (size_t i = 0; i < sizeof(UpgradeCodes) / sizeof(UpgradeCodes[0]); i++) { tstring tstrUpgradeCode = UpgradeCodes[i]; DWORD dwIndex = 0; size_t status; // for each of the upgrade code, get all the products do { status = MsiEnumRelatedProducts(UpgradeCodes[i], 0, dwIndex, lpProductCode); if (ERROR_SUCCESS == status) { UINT uiReturn = MsiConfigureProductEx(lpProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, tszNoReboot); if (ERROR_SUCCESS_REBOOT_REQUIRED == uiReturn) { // prompt for reboot at the end of all modules uninstallation. } if (ERROR_SUCCESS != uiReturn) { // log message with return code. // Error Code: 1605 is coming from here. } } }while (ERROR_NO_MORE_ITEMS != status); } 
+6
source share
4 answers

It is possible that the previous uninstallation of your product left something registered during the uninstallation, and this causes all the problems. I would try to check with scripts what is registered in the system.

Good discussions found on extracting product information with VBScript here, a couple of really good scripts - recommended . Go to sites to find scripts, they are rather poorly formatted here and clog the answer.

The Windows Installer database is located here:

  • HKEY_CLASSES_ROOT \ Installer \
  • Upgrade Code Section: HKEY_CLASSES_ROOT \ Installer \ UpgradeCodes

You should never touch anything in the registry of the Windows Installer database directly. It is extremely interconnected and easily corrupt. Only go through the API. Please note that the GUIDs in the registry are packed, so you will not find the GUIDs from the package in the registry.

  • Packaged GUID : 03B1692A57845354EA63AD602436AB05
  • Regular GUID : {A2961B30-4875-4535-AE36-DA064263BA50}

Using the VBScripts above and the registry data directly for verification, you can determine what is happening in the Windows Installer database.

+4
source

I would never work directly in C ++ to test this. Instead, I would fix some complexity by trying PowerShell or VBScript to determine what is wrong with the uninstall procedure. You can find information on how to use these scripting tools here in this thread . And here is another stream.

  • It is not clear if any of the remote computers are working, and is there one that fails or if the delete operation completes completely? This is the first question.
  • Have you tried to manually remove all products from add / remove to make sure that all of them are deleted correctly manually? One of the products may cause an error return code during uninstallation, which is caught programmatically but is ignored during manual installation. Often these can be from custom actions placed after InstallFinalize . In this case, a redesign of the setting is required. In the simplest case, this will disable error checking for the user action, but this fix is ​​not enough in my opinion.
  • It is possible that the product is installed, but for the user . In other words, it can be set for only one user on the machine, and not for the machine (this is controlled by the ALLUSERS property). I'm not sure how this function works, if so - it can even report the product as advertised (available for installation on demand using a shortcut, but not actually installed). Again, I have not tried this, and deletion may still work. Just from the head to try to give you some pointers.
  • Have you made any major updates to existing MSI files as part of your product installation?

One more question : do you work in Windows 8? And are these .msi files generated using WIX or another tool? There have been periodic reports of problems that are at least remotely similar .

+2
source

If you have a package installer (such as Microsoft SQL Server), it can install many other items during the installation phase.

Later, when you proceed to uninstall the installer of a large package, all the elements that the installer adds to the system should theoretically be removed.

So, try just uninstalling the application, stop and then see if all the other applications are still on the system.

If so, you will need to remove these individual applications first when your user uninstall script begins.

I assume that you already have the System.Configuration.Install.Installer class. Following the instructions for installing the application (1, 2, 3, etc.), perform the following steps in reverse order when uninstalling the application (3, 2, 1).

+2
source

Try a new approach for you. I found two products that apparently have at least two product codes registered for their update codes. They are: MSVC redistributable 2008 and MSXML 4.0 SP2 . I wrote a little C ++ - a test that seems to work fine.

Essentially, it seems to me that you need to check ERROR_NO_MORE_ITEMS before the next iteration of the loop so that you do not try to remove products that are no longer installed.

Here is the code VS2013 Which should compile out of the box in a new installation, empty project.


UPDATE : Updated code to use VS2017 and a minimal console application.

  • Create a new console project: File => New => Project... => Visual C++, Windows Desktop, Windows Console Application

  • Paste the code below into the main CPP file (replacing everything that is there)

  • Set a breakpoint and execute and start ( F5 )

  • F10 to go through

  • If "Microsoft Visual C ++ 2008 Redistributable" is not installed, the corresponding product codes will not be found.


 #pragma once #include "stdafx.h" // The below should really be in stdafx.h (precompiled header) #define WIN32_LEAN_AND_MEAN // Exclude stuff from Windows.h #define STRICT #include <windows.h> #include <msi.h> #pragma comment(lib, "msi.lib") // To make code link int main() { UINT i = 0; UINT status = ERROR_SUCCESS; TCHAR productcode[39] = {}; const TCHAR upgradecode[39] = L"{AA783A14-A7A3-3D33-95F0-9A351D530011}"; //Microsoft Visual C++ 2008 Redistributable //const TCHAR upgradecode[39] = L"{7CE723E3-E56B-432C-9F24-78C0606045A5}"; // MSXML 4.0 SP2 (KB973688) do { // look up (related) product code(s) for specified upgrade code status = MsiEnumRelatedProducts(upgradecode, 0, i, productcode); if (status == ERROR_NO_MORE_ITEMS) // Test here. 259, ERROR_NO_MORE_ITEMS { // No more productcodes for specified upgrade code MessageBox(NULL, L"No more productcodes", L"Done", MB_OK); break; // exit do-while loop } i++; // Next product code MessageBox(NULL, productcode, L"Product Code:", MB_OK); } while (status != ERROR_NO_MORE_ITEMS); return 0; } 

Your system may have anonymously registered products due to failed major updates or similar extended error scenarios, so I'm not sure if this solves your problem. p>

Keep in mind that the Windows Installer database at HKEY_CLASSES_ROOT \ Installer \ UpgradeCodes contains packaged GUIDs . You can try the VBScript code found in the following link to convert between packaged and regular GUID formats: http://www.symantec.com/connect/blogs/guid-converter

More about guid formats here if interested: http://www.symantec.com/connect/articles/working-darwin-descriptors

// TEST DATA 2014 (guides in different formats):

 // UpgradeCode // 41A387AA3A7A33D3590FA953D1350011 => {AA783A14-A7A3-3D33-95F0-9A351D530011} // // ProductCode // // Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148 // CFD2C1F142D260E3CB8B271543DA9F98 => {1F1C2DFC-2D24-3E06-BCB8-725134ADF989} // // Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.17 // D20352A90C039D93DBF6126ECE614057 => {9A25302D-30C0-39D9-BD6F-21E6EC160475} // UpgradeCode // 3E327EC7B65EC234F942870C0606545A => {7CE723E3-E56B-432C-9F24-78C0606045A5} // // ProductCode // // MSXML 4.0 SP2 (KB973688) // 6E8A266FCD4F2A1409E1C8110F44DBCE => {F662A8E6-F4DC-41A2-901E-8C11F044BDEC} // MSXML 4.0 SP2 (KB954430) // DDA39468D428E8B4DB27C8D5DC5CA217 => {86493ADD-824D-4B8E-BD72-8C5DCDC52A71} 
+1
source

Source: https://habr.com/ru/post/957089/


All Articles