Поделиться через


Добавление настраиваемых действий в ProgressBar

Пользовательские действия могут добавлять сведения о времени и ходе выполнения в элемент управления ProgressBar . Дополнительные сведения о создании диалогового окна отображения действия с элементом ProgressBar см. в разделе Создание элемента управления ProgressBar.

Обратите внимание, что в пакет установщика Windows необходимо добавить два настраиваемых действия, чтобы точно передавать сведения о времени и ходе выполнения в ProgressBar. Одно настраиваемое действие должно быть отложенным пользовательским действием. Это настраиваемое действие должно завершить пользовательскую установку и отправить количество отдельных приращений в элемент управления ProgressBar , когда установщик запускает скрипт установки. Второе настраиваемое действие должно быть немедленным пользовательским действием, которое сообщает ProgressBar, сколько тактов необходимо добавить к общему количеству на этапе приобретения и создания скрипта установки.

Добавление настраиваемого действия в ProgressBar

  1. Определите, как пользовательское действие будет описывать ход выполнения. Например, настраиваемое действие, которое устанавливает разделы реестра, может отображать сообщение о ходе выполнения и обновлять ProgressBar каждый раз, когда установщик записывает один раздел реестра.

  2. Каждое обновление пользовательским действием изменяет длину ProgressBar на постоянный шаг. Укажите или вычислите количество тактов в каждом шаге. Обычно изменение длины ProgressBar в один тик соответствует установке одного байта. Например, если установщик устанавливает около 10 000 байт при записи одного раздела реестра, можно указать, что приращение составляет 10 000 тактов.

  3. Укажите или вычислите общее количество тактов, добавляемых настраиваемым действием к длине ProgressBar. Количество тактов, добавляемых пользовательским действием, обычно вычисляется следующим образом: (приращение деления) x (количество элементов). Например, если настраиваемое действие записывает 10 разделов реестра, установщик устанавливает около 10 0000 байт, и поэтому установщик должен увеличить оценку итоговой общей длины ProgressBar на 100 000 тактов.

    Примечание

    Для динамического вычисления настраиваемое действие должно содержать раздел, который немедленно выполняется во время создания скрипта. Количество тактов, сообщаемых пользовательским действием отложенного выполнения, должно быть равно количеству тактов, добавленным к общему количеству тактов при немедленном выполнении. Если это не так, оставшееся время, указанное элементом управления текстом TimeRemaining, будет неточным.

     

  4. Разделите настраиваемое действие на два раздела кода: раздел, который выполняется на этапе создания скрипта, и раздел, который выполняется на этапе выполнения установки. Для этого можно использовать два файла или один файл, определив режим запуска установщика. В следующем примере используется один файл и проверяется состояние установки. Разделы примера должны выполняться в зависимости от того, находится ли установщик на этапе выполнения или создания скрипта установки.

  5. Раздел, выполняемый во время создания скрипта, должен увеличить оценку итоговой общей длины ProgressBar на общее количество тактов в настраиваемом действии. Для этого отправляется сообщение о ходе выполнения ProgressAddition .

  6. Раздел, выполняемый на этапе выполнения установки, должен настроить текст сообщения и шаблоны, чтобы сообщить пользователю о том, что выполняет настраиваемое действие, и направить установщик на обновление элемента управления ProgressBar . Например, сообщите установщику о необходимости перемещения ProgressBar вперед на один шаг и отправки явного сообщения о ходе выполнения при каждом обновлении. Обычно в этом разделе есть цикл, если настраиваемое действие устанавливает что-то. При каждом прохождении этого цикла установщик может установить один ссылочный элемент, например раздел реестра, и обновить элемент управления ProgressBar.

  7. Добавьте настраиваемое действие немедленного выполнения в пакет установщика Windows. Это настраиваемое действие сообщает ProgressBar , сколько необходимо продвинуться на этапах приобретения и создания скрипта установки. В следующем примере источником является библиотека DLL, созданная путем компиляции примера кода, а целевой — точка входа CAProgress.

  8. Добавьте настраиваемое действие отложенного выполнения в пакет установщика Windows. Это настраиваемое действие завершает шаги фактической установки и сообщает ProgressBar , насколько нужно продвинуть панель во время запуска установщиком скрипта установки. В следующем примере источником является библиотека DLL, созданная путем компиляции примера кода, а целевой — точка входа CAProgress.

  9. Запланируйте пользовательские действия между InstallInitialize и InstallFinalize в таблице InstallExecuteSequence . Отложенное настраиваемое действие должно быть запланировано сразу после немедленного выполнения настраиваемого действия. Установщик не будет запускать отложенное настраиваемое действие, пока не будет выполнен скрипт.

В следующем примере показано, как добавить настраиваемое действие в ProgressBar. Источником обоих настраиваемых действий является библиотека DLL, созданная путем компиляции примера кода, а целью обоих настраиваемых действий является точка входа CAProgress. Этот пример не вносит фактических изменений в систему, но работает с ProgressBar так, как если бы установка 10 ссылочных элементов размером примерно 10 000 байт. Установщик обновляет сообщение и 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;
     }
}