Share via


卸載修補程式

從 Windows Installer 3.0 開始,您可以從應用程式卸載某些修補程式。 修補程式必須是 可卸載的修補程式。 使用小於 3.0 版的 Windows Installer 版本時, 移除修補程式 需要卸載修補程式產品,並重新安裝產品而不套用修補程式。

Windows Installer 2.0: 不支援。 使用早于 Windows Installer 3.0 的 Windows Installer 版本所套用的修補程式無法卸載。

當您透過下列任何方法叫用修補程式的卸載時,安裝程式會嘗試從應用程式或要求卸載的使用者看到的第一個產品中移除修補程式。 安裝程式會依下列順序搜尋已修補的產品:每一使用者管理、每一使用者非受控、每部電腦。

在命令列上使用 MSIPATCHREMOVE 卸載修補程式

您可以使用 msiexec.exe 和 命令列選項,從命令卸載修補程式。 下列範例命令列會使用MSIPATCHREMOVE屬性和 /i 命令列選項,從應用程式移除可卸載的修補程式example.msp example.msi。 使用 /i 時,修補的應用程式可以透過應用程式套件 (.msi 檔案的路徑來識別) 或應用程式的 產品代碼。 在此範例中,應用程式的安裝套件位於 「\\server\share\products\example\example.msi」,而應用程式的 ProductCode 屬性為 「{0C9840E7-7F0B-C648-10F0-4641926FE463}」。 修補程式套件位於 「\\server\share\products\example\patchs\example.msp」,修補程式碼 GUID 是 「{EB8C947C-78B2-85A0-644D-86CEEF8E07C0}」。

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

使用標準命令列選項卸載修補程式

從 Windows Installer 3.0 版開始,您可以使用 Microsoft Windows 作業系統更新 (update.exe 所使用的標準命令列選項,) 從命令列卸載 Windows Installer 修補程式。

下列命令列是標準命令列,相當於使用 MSIPATCHREMOVE 屬性卸載修補程式的 Windows Installer 命令列。 與 /package 選項搭配使用的 /uninstall 選項代表修補程式的卸載。 修補程式可以透過修補程式的完整路徑或修補程式程式碼 GUID 來參考。

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

注意

/passive 標準選項與 Windows Installer /qb 選項不完全相等。

 

使用 RemovePatches 方法卸載修補程式

您可以使用 Windows Installer 自動化介面,從腳本卸載修補程式。 下列腳本範例會使用Installer物件的RemovePatches方法,從應用程式中移除uninstallable patch example.msp,example.msi。 每個要卸載的修補程式都可以由修補程式套件的完整路徑或修補程式程式碼 GUID 來表示。 在此範例中,應用程式的安裝套件位於 「\\server\share\products\example\example.msi」,而應用程式的 ProductCode 屬性為 「{0C9840E7-7F0B-C648-10F0-4641926FE463}」。 修補程式套件位於 「\\server\share\products\example\patchs\example.msp」,修補程式碼 GUID 是 「{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, "")

使用新增/移除程式卸載修補程式

使用 Windows XP,您可以使用 [新增/移除程式] 卸載修補程式。

使用 MsiRemovePatches 函式卸載修補程式

您的應用程式可以使用 Windows Installer Functions從其他應用程式卸載修補程式。 下列程式碼範例會使用MsiRemovePatches函式,從應用程式移除可卸載的修補程式example.msp example.msi。 修補程式可以透過修補程式套件的完整路徑或修補程式程式碼 GUID 來參考。 在此範例中,應用程式的安裝套件位於 「\\server\share\products\example\example.msi」,而應用程式的 ProductCode 屬性為 「{0C9840E7-7F0B-C648-10F0-4641926FE463}」。 修補程式套件位於 「\\server\share\products\example\patchs\example.msp」,修補程式碼 GUID 是 「{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 函式從所有應用程式卸載修補程式

單一修補程式可以更新電腦上的多個產品。 應用程式可以使用 MsiEnumProductsEx 列舉電腦上的所有產品,並判斷修補程式是否已套用至產品的特定實例。 然後,應用程式可以使用 MsiRemovePatches卸載修補程式。 例如,如果修補程式更新由多個產品共用的元件中的檔案,且修補程式會散發以更新這兩項產品,則單一修補程式可以更新多個產品。

下列範例示範應用程式如何使用 Windows Installer,從使用者可用的所有應用程式中移除修補程式。 它不會從針對另一位使用者安裝的應用程式移除修補程式。

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

修補程式排序

移除修補程式

可卸載的修補程式

修補卸載自訂動作

MSIPATCHREMOVE

MsiEnumapplicationsEx

MsiGetPatchInfoEx

MsiRemovePatches