패치 제거
Windows Installer 3.0부터 애플리케이션에서 일부 패치를 제거할 수 있습니다. 패치는 제거할 수 없는 패치여야 합니다. 버전 3.0 미만의 Windows Installer 버전을 사용하는 경우 패치를 제거하려면 패치 제품을 제거한 다음 패치를 적용하지 않고 제품을 다시 설치해야 합니다.
Windows Installer 2.0: 지원되지 않습니다. Windows Installer 3.0 이전 버전의 Windows Installer를 사용하여 적용된 패치는 제거할 수 없습니다.
다음 방법 중 하나로 패치 제거를 호출하면 설치 관리자는 제거를 요청하는 애플리케이션 또는 사용자에게 표시되는 첫 번째 제품에서 패치를 제거하려고 시도합니다. 설치 관리자는 사용자별 관리형, 사용자별 비관리형, 머신별 순서로 패치된 제품을 검색합니다.
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 옵션과 정확히 동일하지 않습니다.
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를 사용하면 프로그램 추가/제거를 사용하여 패치를 제거할 수 있습니다.
애플리케이션은 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);
단일 패치는 컴퓨터에서 둘 이상의 제품을 업데이트할 수 있습니다. 애플리케이션은 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;
}