다음을 통해 공유


ProgressBar에 사용자 지정 작업 추가

사용자 지정 작업ProgressBar 컨트롤에 시간 및 진행률 정보를 추가할 수 있습니다. ProgressBar가 있는 작업 표시 대화 상자를 만드는 방법에 대한 자세한 내용은 ProgressBar 컨트롤 작성을 참조하세요.

시간 및 진행률 정보를 ProgressBar에 정확하게 보고하려면 Windows Installer 패키지에 두 개의 사용자 지정 작업을 추가해야 합니다. 하나의 사용자 지정 작업은 지연된 사용자 지정 작업이어야 합니다. 이 사용자 지정 작업은 사용자 지정 설치를 완료하고 설치 관리자가 설치 스크립트를 실행할 때 개별 증분을 ProgressBar 컨트롤로 보내야 합니다. 두 번째 사용자 지정 작업은 설치의 획득 및 스크립트 생성 단계에서 총 수에 추가할 틱 수를 ProgressBar에 알리는 즉각적인 실행 사용자 지정 작업이어야 합니다.

ProgressBar에 사용자 지정 작업을 추가하려면

  1. 사용자 지정 작업에서 진행 상황을 설명하는 방법을 결정합니다. 예를 들어 레지스트리 키를 설치하는 사용자 지정 작업은 설치 관리자가 하나의 레지스트리 키를 쓸 때마다 진행률 메시지를 표시하고 ProgressBar를 업데이트할 수 있습니다.

  2. 사용자 지정 작업에 의한 각 업데이트는 ProgressBar의 길이를 일정하게 증가하게 합니다. 각 증분에서 틱 수를 지정하거나 계산합니다. 일반적으로 틱 하나의 ProgressBar 길이 변경은 1바이트 설치에 해당합니다. 예를 들어 설치 프로그램이 하나의 레지스트리 키를 쓸 때 약 10,000바이트를 설치하는 경우 증분에 10,000틱이 있도록 지정할 수 있습니다.

  3. 사용자 지정 작업이 ProgressBar의 길이에 추가하는 총 틱 수를 지정하거나 계산합니다. 사용자 지정 작업에 의해 추가된 틱 수는 일반적으로 (틱 증가) x (항목 수)로 계산됩니다. 예를 들어 사용자 지정 작업이 10개의 레지스트리 키를 쓰는 경우 설치 관리자는 약 100,000바이트를 설치하므로 설치 관리자는 ProgressBar의 최종 총 길이 추정치를 100,000틱 늘려야 합니다.

    참고

    이를 동적으로 계산하려면 사용자 지정 작업에 스크립트 생성 중에 즉시 실행되는 섹션이 포함되어야 합니다. 지연 실행 사용자 지정 작업에서 보고한 틱 수는 즉시 실행 작업에서 총 틱 수에 추가한 틱 수와 같아야 합니다. 그렇지 않은 경우 TimeRemaining 텍스트 컨트롤에서 보고한 남은 시간은 정확하지 않습니다.

     

  4. 사용자 지정 작업을 두 개의 코드 섹션, 즉 스크립트 생성 단계에서 실행되는 섹션과 설치의 실행 단계에서 실행되는 섹션으로 구분합니다. 이 작업은 두 개의 파일을 사용하거나 설치 관리자의 실행 모드에서 컨디셔닝하여 하나의 파일을 사용할 수 있습니다. 다음 샘플에서는 하나의 파일을 사용하고 설치 상태를 확인합니다. 샘플의 섹션은 설치 관리자가 설치의 실행 또는 스크립트 생성 단계에 있는지 여부에 따라 실행되도록 조건화됩니다.

  5. 스크립트 생성 중에 실행되는 섹션은 ProgressBar의 최종 총 길이 추정치를 사용자 지정 작업의 총 틱 수만큼 늘려야 합니다. 이는 ProgressAddition 진행 메시지를 전송하여 수행됩니다.

  6. 설치 실행 단계 중에 실행되는 섹션은 메시지 텍스트와 템플릿을 설정하여 사용자 지정 작업이 수행하는 작업에 대해 사용자에게 알리고 설치 관리자가 ProgressBar 컨트롤을 업데이트하도록 지시해야 합니다. 예를 들어 ProgressBar를 한 단계 앞으로 이동하고 업데이트할 때마다 명시적인 진행률 메시지를 보내도록 설치 관리자에 알립니다. 사용자 지정 작업이 무언가를 설치하는 경우 일반적으로 이 섹션에 루프가 있습니다. 이 루프를 통과할 때마다 설치 관리자는 레지스트리 키와 같은 하나의 참조 항목을 설치하고 ProgressBar 컨트롤을 업데이트할 수 있습니다.

  7. Windows Installer 패키지에 즉시 실행 사용자 지정 작업을 추가합니다. 이 사용자 지정 작업은 설치의 획득 및 스크립트 생성 단계에서 진행해야 할 진행 정도를 ProgressBar에 알릴 수 있습니다. 다음 샘플의 경우 원본은 샘플 코드를 컴파일하여 만든 DLL이고 대상은 진입점인 CAProgress입니다.

  8. Windows Installer 패키지에 지연된 실행 사용자 지정 작업을 추가합니다. 이 사용자 지정 작업은 실제 설치 단계를 완료하고 설치 관리자가 설치 스크립트를 실행할 때 막대를 얼마나 진행할지 ProgressBar에 알릴 수 있습니다. 다음 샘플의 경우 원본은 샘플 코드를 컴파일하여 만든 DLL이고 대상은 진입점인 CAProgress입니다.

  9. InstallExecuteSequence 테이블에서 InstallInitializeInstallFinalize 사이에 두 가지 맞춤 작업을 모두 예약합니다. 지연된 사용자 지정 작업은 즉시 실행 사용자 지정 작업 직후에 예약되어야 합니다. 설치 관리자는 스크립트가 실행될 때까지 지연된 사용자 지정 작업을 실행하지 않습니다.

다음 샘플에서는 사용자 지정 작업을 ProgressBar에 추가하는 방법을 보여 줍니다. 두 사용자 지정 작업의 원본은 샘플 코드를 컴파일하여 만든 DLL이며 두 사용자 지정 작업의 대상은 진입점인 CAProgress입니다. 이 샘플은 시스템을 실제로 변경하지는 않지만 크기가 약 10,000바이트인 10개의 참조 항목을 설치하는 것처럼 ProgressBar를 작동합니다. 설치 관리자는 참조 항목을 설치할 때마다 메시지와 ProgressBar를 업데이트합니다.

#include <windows.h>
#include <msiquery.h>
#pragma comment(lib, "msi.lib")

// Specify or calculate the number of ticks in an increment
// to the ProgressBar
const UINT iTickIncrement = 10000;
 
// Specify or calculate the total number of ticks the custom 
// action adds to the length of the ProgressBar
const UINT iNumberItems = 10;
const UINT iTotalTicks = iTickIncrement * iNumberItems;
 
UINT __stdcall CAProgress(MSIHANDLE hInstall)
{
    // Tell the installer to check the installation state and execute
    // the code needed during the rollback, acquisition, or
    // execution phases of the installation.
  
    if (MsiGetMode(hInstall,MSIRUNMODE_SCHEDULED) == TRUE)
    {
        PMSIHANDLE hActionRec = MsiCreateRecord(3);
        PMSIHANDLE hProgressRec = MsiCreateRecord(3);

        // Installer is executing the installation script. Set up a
        // record specifying appropriate templates and text for
        // messages that will inform the user about what the custom
        // action is doing. Tell the installer to use this template and 
        // text in progress messages.
 
        MsiRecordSetString(hActionRec, 1, TEXT("MyCustomAction"));
        MsiRecordSetString(hActionRec, 2, TEXT("Incrementing the Progress Bar..."));
        MsiRecordSetString(hActionRec, 3, TEXT("Incrementing tick [1] of [2]"));
        UINT iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONSTART, hActionRec);
        if ((iResult == IDCANCEL))
            return ERROR_INSTALL_USEREXIT;
              
        // Tell the installer to use explicit progress messages.
        MsiRecordSetInteger(hProgressRec, 1, 1);
        MsiRecordSetInteger(hProgressRec, 2, 1);
        MsiRecordSetInteger(hProgressRec, 3, 0);
        iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hProgressRec);
        if ((iResult == IDCANCEL))
            return ERROR_INSTALL_USEREXIT;
              
        //Specify that an update of the progress bar's position in
        //this case means to move it forward by one increment.
        MsiRecordSetInteger(hProgressRec, 1, 2);
        MsiRecordSetInteger(hProgressRec, 2, iTickIncrement);
        MsiRecordSetInteger(hProgressRec, 3, 0);
 
        // The following loop sets up the record needed by the action
        // messages and tells the installer to send a message to update
        // the progress bar.

        MsiRecordSetInteger(hActionRec, 2, iTotalTicks);
       
        for( int i = 0; i < iTotalTicks; i+=iTickIncrement)
        {
            MsiRecordSetInteger(hActionRec, 1, i);

            iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONDATA, hActionRec);
            if ((iResult == IDCANCEL))
                return ERROR_INSTALL_USEREXIT;
          
            iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hProgressRec);
            if ((iResult == IDCANCEL))
                return ERROR_INSTALL_USEREXIT;
   
            //A real custom action would have code here that does a part
            //of the installation. For this sample, code that installs
            //10 registry keys.
            Sleep(1000);
                    
        }
        return ERROR_SUCCESS;
    }
    else
    {
        // Installer is generating the installation script of the
        // custom action.
  
        // Tell the installer to increase the value of the final total
        // length of the progress bar by the total number of ticks in
        // the custom action.
        PMSIHANDLE hProgressRec = MsiCreateRecord(2);

         MsiRecordSetInteger(hProgressRec, 1, 3);
            MsiRecordSetInteger(hProgressRec, 2, iTotalTicks);
        UINT iResult = MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hProgressRec);
           if ((iResult == IDCANCEL))
            return ERROR_INSTALL_USEREXIT;     
        return ERROR_SUCCESS;
     }
}