다음을 통해 공유


패치 제거

Windows Installer 3.0부터 애플리케이션에서 일부 패치를 제거할 수 있습니다. 패치는 제거할 수 없는 패치여야 합니다. 버전 3.0 미만의 Windows Installer 버전을 사용하는 경우 패치를 제거하려면 패치 제품을 제거한 다음 패치를 적용하지 않고 제품을 다시 설치해야 합니다.

Windows Installer 2.0: 지원되지 않습니다. Windows Installer 3.0 이전 버전의 Windows Installer를 사용하여 적용된 패치는 제거할 수 없습니다.

다음 방법 중 하나로 패치 제거를 호출하면 설치 관리자는 제거를 요청하는 애플리케이션 또는 사용자에게 표시되는 첫 번째 제품에서 패치를 제거하려고 시도합니다. 설치 관리자는 사용자별 관리형, 사용자별 비관리형, 머신별 순서로 패치된 제품을 검색합니다.

명령줄에서 MSIPATCHREMOVE를 사용하여 패치 제거

msiexec.exe 및 명령 줄 옵션을 사용하여 명령에서 패치를 제거할 수 있습니다. 다음 샘플 명령줄은 MSIPATCHREMOVE 속성 및 /i 명령줄 옵션을 사용하여 애플리케이션 example.msi에서 제거할 수 없는 패치 example.msp를 제거합니다. /i를 사용하는 경우, 패치된 애플리케이션은 애플리케이션의 패키지(.msi 파일) 또는 애플리케이션의 제품 코드에 대한 경로로 식별할 수 있습니다. 이 예제에서 애플리케이션의 설치 패키지는 “\\server\share\products\example\example.msi”에 있으며 애플리케이션의 ProductCode 속성은 “{0C9840E7-7F0B-C648-10F0-4641926FE463}”입니다. 패치 패키지는 “\\server\share\products\example\patches\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 Automation 인터페이스를 사용하여 스크립트에서 패치를 제거할 수 있습니다. 다음 스크립팅 샘플은 Installer 개체의 RemovePatches 메서드를 사용하여 애플리케이션 example.msi에서 제거할 수 없는 패치 example.msp를 제거합니다. 제거되는 각 패치는 패치 패키지에 대한 전체 경로 또는 패치 코드 GUID로 표시될 수 있습니다. 이 예제에서 애플리케이션의 설치 패키지는 “\\server\share\products\example\example.msi”에 있으며 애플리케이션의 ProductCode 속성은 “{0C9840E7-7F0B-C648-10F0-4641926FE463}”입니다. 패치 패키지는 “\\server\share\products\example\patches\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 함수를 사용하여 다른 애플리케이션에서 패치를 제거할 수 있습니다. 다음 코드 예제에서는 MsiRemovePatches 함수를 사용하여 애플리케이션 example.msi에서 제거할 수 없는 패치 example.msp를 제거합니다. 패치 패키지에 대한 전체 경로 또는 패치 코드 GUID를 통해 패치를 참조할 수 있습니다. 이 예제에서 애플리케이션의 설치 패키지는 “\\server\share\products\example\example.msi”에 있으며 애플리케이션의 ProductCode 속성은 “{0C9840E7-7F0B-C648-10F0-4641926FE463}”입니다. 패치 패키지는 “\\server\share\products\example\patches\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