Como desinstalar patches

A partir do Windows Installer 3.0, é possível desinstalar alguns patches dos aplicativos. O patch deve ser um patch desinstalável. Ao usar uma versão do Windows Installer anterior à versão 3.0, a remoção de patches requer desinstalar o produto de patch e reinstalar o produto sem aplicar o patch.

Windows Installer 2.0: sem suporte. Patches aplicados usando uma versão do Windows Installer anterior ao Windows Installer 3.0 não poderão ser desinstalados.

Quando você invoca uma desinstalação de um patch usando qualquer um dos métodos a seguir, o instalador tenta remover o patch do primeiro produto visível para o aplicativo ou usuário que solicita a desinstalação. O instalador pesquisa os produtos corrigidos na seguinte ordem: por usuário gerenciado, por usuário não gerenciado, por computador.

Como desinstalar um patch usando o MSIPATCHREMOVE em uma linha de comando

Você pode desinstalar patches de um comando usando o msiexec.exe e as Opções de Linha de Comando. A linha de comando de exemplo a seguir remove um patch desinstalável, example.msp, de um aplicativo, example.msi, usando a propriedade MSIPATCHREMOVE e a opção de linha de comando /i. Ao usar /i, o aplicativo corrigido pode ser identificado pelo caminho para o pacote do aplicativo (arquivo .msi) ou o código do produto do aplicativo. Neste exemplo, o pacote de instalação do aplicativo está localizado em "\\server\share\products\example\example.msi" e a propriedade ProductCode do aplicativo é "{0C9840E7-7F0B-C648-10F0-4641926FE463}". O pacote de patch está localizado em "\\server\share\products\example\patches\example.msp" e o GUID do código de patch é "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}".

Msiexec /I {0C9840E7-7F0B-C648-10F0-4641926FE463} MSIPATCHREMOVE={EB8C947C-78B2-85A0-644D-86CEEF8E07C0} /qb

Como desinstalar um patch usando as opções de linha de comando padrão

A partir do Windows Installer versão 3.0, você pode usar as opções de linha de comando padrão usadas pelo Microsoft Windows Operating System Atualizações (update.exe) para desinstalar patches do Windows Installer em uma linha de comando.

A linha de comando a seguir é o equivalente à linha de comando padrão da linha de comando do Windows Installer usada para desinstalar um patch usando a propriedade MSIPATCHREMOVE. A opção /uninstall usada com a opção /package indica a desinstalação de um patch. O patch pode ser referenciado pelo caminho completo para o patch ou pelo GUID do código de patch.

Msiexec /package {0C9840E7-7F0B-C648-10F0-4641926FE463} /uninstall {EB8C947C-78B2-85A0-644D-86CEEF8E07C0} /passive

Observação

A opção /passive standard não é uma opção equivalente exata da opção /qb do Windows Installer.

 

Como desinstalar um patch usando o método RemovePatches

Você pode desinstalar patches do script usando a Interface de Automação do Windows Installer. O exemplo de script a seguir remove um patch desinstalável, example.msp, de um aplicativo, example.msi, usando o método RemovePatches do objeto Installer. Cada patch que está sendo desinstalado pode ser representado pelo caminho completo para o pacote de patch ou o GUID do código de patch. Neste exemplo, o pacote de instalação do aplicativo está localizado em "\\server\share\products\example\example.msi" e a propriedade ProductCode do aplicativo é "{0C9840E7-7F0B-C648-10F0-4641926FE463}". O pacote de patch está localizado em "\\server\share\products\example\patches\example.msp" e o GUID do código de patch é "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}".

const msiInstallTypeSingleInstance = 2
const PatchList = "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}"
const Product = "{0C9840E7-7F0B-C648-10F0-4641926FE463}"

Dim installer
Set installer = CreateObject("WindowsInstaller.Installer")

installer.RemovePatches(PatchList, Product, msiInstallTypeSingleInstance, "")

Como desinstalar um patch usando a opção Adicionar/Remover Programas

Com o Windows XP, você pode desinstalar patches usando a opção Adicionar/Remover Programas.

Como desinstalar um patch usando a função MsiRemovePatches

Seus aplicativos podem desinstalar patches de outros aplicativos usando as Funções do Windows Installer. O exemplo de código a seguir remove um patch desinstalável, example.msp, de um aplicativo, example.msi, usando a função MsiRemovePatches. Um patch pode ser referenciado pelo caminho completo para o pacote de patch ou o GUID do código de patch. Neste exemplo, o pacote de instalação do aplicativo está localizado em "\\server\share\products\example\example.msi" e a propriedade ProductCode do aplicativo é "{0C9840E7-7F0B-C648-10F0-4641926FE463}". O pacote de patch está localizado em "\\server\share\products\example\patches\example.msp" e o GUID do código de patch é "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}".

    UINT uiReturn = MsiRemovePatches(
          /*szPatchList=*/TEXT("\\server\\share\\products\\example\\patches\\example.msp"),
          /*szProductCode=*/  TEXT("{0C9840E7-7F0B-C648-10F0-4641926FE463}"),
          /*eUninstallType=*/ INSTALLTYPE_SINGLE_INSTANCE,
          /*szPropertyList=*/ NULL);

Como desinstalar um patch de todos os aplicativos usando a função MsiRemovePatches

Um único patch pode atualizar mais de um produto no computador. Um aplicativo pode usar o MsiEnumProductsEx para enumerar todos os produtos no computador e determinar se um patch foi aplicado a uma instância específica do produto. Em seguida, o aplicativo pode desinstalar o patch usando MsiRemovePatches. Por exemplo, um único patch poderá atualizar vários produtos, se o patch atualizar um arquivo em um componente compartilhado por vários produtos e o patch for distribuído para atualizar ambos os produtos.

O exemplo a seguir demonstra como um aplicativo pode usar o Windows Installer para remover um patch de todos os aplicativos disponíveis para o usuário. Isso não remove o patch de aplicativos instalados por usuário para outro usuário.

#ifndef UNICODE
#define UNICODE
#endif //UNICODE

#ifndef _WIN32_MSI
#define _WIN32_MSI 300
#endif //_WIN32_MSI

#include <stdio.h>
#include <windows.h>
#include <msi.h>

#pragma comment(lib, "msi.lib")

const int cchGUID = 38;

///////////////////////////////////////////////////////////////////
// RemovePatchFromAllVisibleapplications:
//
// Arguments:
//    wszPatchToRemove - GUID of patch to remove
//
///////////////////////////////////////////////////////////////////
//
UINT RemovePatchFromAllVisibleapplications(LPCWSTR wszPatchToRemove)
{
    if (!wszPatchToRemove)
        return ERROR_INVALID_PARAMETER;

    UINT uiStatus = ERROR_SUCCESS;
    DWORD dwIndex = 0;
    WCHAR wszapplicationCode[cchGUID+1] = {0};

    DWORD dwapplicationSearchContext = MSIINSTALLCONTEXT_ALL;
    MSIINSTALLCONTEXT dwInstallContext = MSIINSTALLCONTEXT_NONE;

    do
    {
        // Enumerate all visible applications in all contexts for the caller.
        // NULL for szUserSid defaults to using the caller's SID
        uiStatus = MsiEnumProductsEx(/*szapplicationCode*/NULL,
         /*szUserSid*/NULL,
         dwapplicationSearchContext,
         dwIndex,
         wszapplicationCode,
         &dwInstallContext,
         /*szSid*/NULL,
         /*pcchSid*/NULL);

        if (ERROR_SUCCESS == uiStatus)
        {
            // check to see if the provided patch is
            // registered for this application instance
            UINT uiPatchStatus = MsiGetPatchInfoEx(wszPatchToRemove,
             wszapplicationCode,
             /*szUserSid*/NULL,
             dwInstallContext,
             INSTALLPROPERTY_PATCHSTATE,
             NULL,
             NULL);

            if (ERROR_SUCCESS == uiPatchStatus)
            {
                // patch is registered to this application; remove patch
                wprintf(L"Removing patch %s from application %s...\n",
                 wszPatchToRemove, wszapplicationCode);
                                
                UINT uiRemoveStatus = MsiRemovePatches(
                 wszPatchToRemove,
                 wszapplicationCode,
                 INSTALLTYPE_SINGLE_INSTANCE,
                 L"");

                if (ERROR_SUCCESS != uiRemoveStatus)
                {
                    // This halts the enumeration and fails. Alternatively
                    // you could output an error and continue the
                    // enumeration
                     return ERROR_FUNCTION_FAILED;
                }
            }
            else if (ERROR_UNKNOWN_PATCH != uiPatchStatus)
            {
                // Some other error occurred during processing. This
                // halts the enumeration and fails. Alternatively you
                // could output an error and continue the enumeration
                 return ERROR_FUNCTION_FAILED;
            }
            // else patch was not applied to this application
            // (ERROR_UNKNOWN_PATCH returned)
        }

        dwIndex++;
    }
    while (uiStatus == ERROR_SUCCESS);

    if (ERROR_NO_MORE_ITEMS != uiStatus)
        return ERROR_FUNCTION_FAILED;

    return ERROR_SUCCESS;
}

Sequenciamento de patch

Como remover patches

Patches desinstaláveis

Ações personalizadas de desinstalação de patch

MSIPATCHREMOVE

MsiEnumapplicationsEx

MsiGetPatchInfoEx

MsiRemovePatches