卸载修补程序Uninstalling Patches

从 Windows Installer 3.0 开始,可以从应用程序中卸载一些修补程序。Beginning with Windows Installer 3.0, it is possible to uninstall some patches from applications. 修补程序必须为 可卸载修补程序。The patch must be an uninstallable patch. 当使用低于版本3.0 的 Windows Installer 版本时, 删除修补 程序需要卸载修补程序产品并重新安装产品,而不应用修补程序。When using a Windows Installer version less than version 3.0, removing patches requires uninstalling the patch product and reinstalling the product without applying the patch.

Windows Installer 2.0: 不支持。Windows Installer 2.0: Not supported. 使用早于 Windows Installer 3.0 的 Windows Installer 版本应用的修补程序不可卸载。Patches applied using a version of Windows Installer that is earlier than Windows Installer 3.0 are not uninstallable.

当你通过以下任一方法调用修补程序的卸载时,安装程序将尝试从对应用程序或请求卸载的用户可见的第一个产品中删除修补程序。When you invoke an uninstallation of a patch by any of the following methods, the installer attempts to remove the patch from the first product visible to the application or user requesting the uninstallation. 安装程序将按以下顺序搜索修补后的产品:每个用户管理的、每个用户的非管理、每台计算机。The installer searches for patched products in the following order: per-user managed, per-user unmanaged, per-machine.

在命令行中使用 MSIPATCHREMOVE 卸载修补程序Uninstalling a patch using MSIPATCHREMOVE on a command line

可以通过使用 msiexec.exe 和 命令行选项,从命令中卸载修补程序。You can uninstall patches from a command by using msiexec.exe and the Command Line Options. 下面的示例命令行使用 MSIPATCHREMOVE属性和/i 命令行选项从应用程序中删除 可卸载修补程序示例 .msp example.msi。The following sample command line removes an uninstallable patch, example.msp, from an application, example.msi, using the MSIPATCHREMOVE property and the /i command line option. 使用/i 时,可以通过应用程序包的路径 ( .msi 文件) 或应用程序的 产品代码来识别修补的应用程序。When using /i, the patched application can be identified by the path to the application's package (.msi file) or the application's product code. 在此示例中,应用程序的安装包位于 " \ \ server \ share \ products \ example \example.msi",应用程序的 " ProductCode " 属性为 "{0C9840E7-7F0B-C648-10F0-4641926FE463}"。In this example, the application's installation package is located at "\\server\share\products\example\example.msi" and the application's ProductCode property is "{0C9840E7-7F0B-C648-10F0-4641926FE463}". 修补程序包位于 " \ \ 服务器 \ 共享 \ 产品 \ 示例 \ \ .MSP" 中,修补程序代码 GUID 为 "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}"。The patch package is located at "\\server\share\products\example\patches\example.msp" and the patch code GUID is "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}".

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

使用标准命令行选项卸载修补程序Uninstalling a patch using the standard command line options

从 Windows Installer 版本3.0 开始,你可以使用 Microsoft Windows 操作系统更新 (update.exe) 使用的 标准命令行选项 从命令行卸载 Windows Installer 修补程序。Beginning with Windows Installer version 3.0, you can use the standard command line options used by Microsoft Windows Operating System Updates (update.exe) to uninstall Windows Installer patches from a command line.

以下命令行是与 Windows Installer 命令行等效的标准命令行,此命令行用于使用 MSIPATCHREMOVE 属性卸载修补程序。The following command line is the standard command line equivalent of the Windows Installer command line used to uninstall a patch using the MSIPATCHREMOVE property. 与 ffe6d16c-3f87-4192-af94-ddbeff165106 选项一起使用的/uninstall 选项表示卸载修补程序。The /uninstall option used with the /package option denotes the uninstallation of a patch. 修补程序可以通过修补程序的完整路径或修补程序代码 GUID 来引用。The patch can be referenced by the full path to the patch or by the patch code GUID.

Msiexec ffe6d16c-3f87-4192-af94-ddbeff165106 {0C9840E7-7F0B-C648-10F0-4641926FE463}/uninstall {EB8C947C-78B2-85A0-644D-86CEEF8E07C0}/passiveMsiexec /package {0C9840E7-7F0B-C648-10F0-4641926FE463} /uninstall {EB8C947C-78B2-85A0-644D-86CEEF8E07C0} /passive

备注

/Passive standard 选项不是 Windows Installer/qb 选项完全相同的选项。The /passive standard option is not an exact equivalent of the Windows Installer /qb option.

使用 RemovePatches 方法卸载修补程序Uninstalling a patch using the RemovePatches method

您可以通过使用 Windows Installer 自动化接口,从脚本中卸载修补程序。You can uninstall patches from script by using the Windows Installer Automation Interface. 以下脚本示例使用 安装程序对象的 RemovePatches方法从应用程序中删除 可卸载修补程序示例 .msp example.msi。The following scripting sample removes an uninstallable patch, example.msp, from an application, example.msi, using the RemovePatches method of the Installer object. 要卸载的每个修补程序都可以使用修补程序包的完整路径或修补程序代码 GUID 来表示。Each patch being uninstalled can be represented by either the full path to the patch package or the patch code GUID. 在此示例中,应用程序的安装包位于 " \ \ server \ share \ products \ example \example.msi",应用程序的 " ProductCode " 属性为 "{0C9840E7-7F0B-C648-10F0-4641926FE463}"。In this example, the application's installation package is located at "\\server\share\products\example\example.msi" and the application's ProductCode property is "{0C9840E7-7F0B-C648-10F0-4641926FE463}". 修补程序包位于 " \ \ 服务器 \ 共享 \ 产品 \ 示例 \ \ .MSP" 中,修补程序代码 GUID 为 "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}"。The patch package is located at "\\server\share\products\example\patches\example.msp" and the patch code GUID is "{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, "")

使用 "添加/删除程序" 卸载修补程序Uninstalling a patch using Add/Remove Programs

使用 Windows XP,你可以使用 "添加/删除程序" 卸载修补程序。With Windows XP, you can uninstall patches using Add/Remove programs.

使用 MsiRemovePatches 函数卸载修补程序Uninstalling a patch using the MsiRemovePatches function

应用程序可以使用 Windows Installer 的函数从其他应用程序中卸载修补程序。Your applications can uninstall patches from other applications by using the Windows Installer Functions. 下面的代码示例使用 MsiRemovePatches函数从应用程序中删除 可卸载修补程序示例 .msp example.msi。The following code example removes an uninstallable patch, example.msp, from an application, example.msi, using the MsiRemovePatches function. 修补程序包的完整路径或修补程序代码 GUID 可以引用修补程序。A patch can be referenced by the full path to the patch package or the patch code GUID. 在此示例中,应用程序的安装包位于 " \ \ server \ share \ products \ example \example.msi",应用程序的 " ProductCode " 属性为 "{0C9840E7-7F0B-C648-10F0-4641926FE463}"。In this example, the application's installation package is located at "\\server\share\products\example\example.msi" and the application's ProductCode property is "{0C9840E7-7F0B-C648-10F0-4641926FE463}". 修补程序包位于 " \ \ 服务器 \ 共享 \ 产品 \ 示例 \ \ .MSP" 中,修补程序代码 GUID 为 "{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}"。The patch package is located at "\\server\share\products\example\patches\example.msp" and the patch code GUID is "{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);

使用 MsiRemovePatches 函数从所有应用程序中卸载修补程序Uninstalling a patch from all applications using MsiRemovePatches function

单个修补程序可以更新计算机上的多个产品。A single patch can update more than one product on the computer. 应用程序可以使用 MsiEnumProductsEx 来枚举计算机上的所有产品,并确定是否已将修补程序应用到产品的特定实例。An application can use MsiEnumProductsEx to enumerate all the products on the computer and determine whether a patch has been applied to a particular instance of the product. 然后,应用程序可以使用 MsiRemovePatches卸载该修补程序。The application can then uninstall the patch using MsiRemovePatches. 例如,如果修补程序更新了多个产品共享的组件中的文件,则单个修补程序可以更新多个产品,并分发修补程序来更新这两种产品。For example, a single patch can update multiple products if the patch updates a file in a component that is shared by multiple products and the patch is distributed to update both products.

下面的示例演示应用程序如何使用 Windows Installer 从可供用户使用的所有应用程序中删除修补程序。The following example demonstrates how an application can use the Windows Installer to remove a patch from all applications that are available to the user. 它不会从每个用户安装的应用程序中删除其他用户的修补程序。It does not remove the patch from applications installed per-user for another user.

#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;
}

修补程序排序Patch Sequencing

删除修补程序Removing Patches

可卸载修补程序Uninstallable Patches

修补卸载自定义操作Patch Uninstall Custom Actions

MSIPATCHREMOVEMSIPATCHREMOVE

MsiEnumapplicationsExMsiEnumapplicationsEx

MsiGetPatchInfoExMsiGetPatchInfoEx

MsiRemovePatchesMsiRemovePatches