Adición de Acciones personalizadas a la barra de progreso

Acciones personalizadas puede agregar información sobre el tiempo y el progreso a un control ProgressBar. Para más información sobre cómo crear un cuadro de diálogo para mostrar una acción con una barra de progreso, consulte Creación de un control ProgressBar.

Tenga en cuenta que se deben agregar dos acciones personalizadas al paquete de Windows Installer para que la información sobre el tiempo y el progreso aparezca correctamente en la barra de progreso. Todas las acciones personalizadas deben ser acciones personalizadas diferidas. Esta acción personalizada debería completar la instalación personalizada y enviar las cantidades de los incrementos individuales al control ProgressBar cuando el instalador ejecute el script de instalación. La segunda acción personalizada debe ser de ejecución inmediata y debe informar a la ProgressBar del número de tics que se agregan al recuento total durante la fase de adquisición y generación de scripts de la instalación.

Para agregar una acción personalizada a la barra de progreso

  1. Decida cómo va a describir la acción personalizada su progreso. Por ejemplo, una acción personalizada que instala claves del Registro puede mostrar un mensaje de progreso y actualizar la barra de progreso cada vez que el instalador escribe una clave del Registro.

  2. Cada actualización que realiza la acción personalizada cambia la longitud de la barra de progreso en un incremento constante. Especifique o calcule el número de tics en cada incremento. Normalmente, si la longitud de la barra de progreso se cambia en tic corresponde a la instalación de un byte. Por ejemplo, si el instalador instala aproximadamente 10 000 bytes cuando escribe una clave del Registro, puede especificar que hay 10 000 tics en un incremento.

  3. Especifique o calcule el número total de tics que la acción personalizada agrega a la longitud de la barra de progreso. Así se calcula normalmente el número de tics que agrega la acción personalizada: (aumento de tics) x (número de elementos). Por ejemplo, si la acción personalizada escribe 10 claves del Registro, el instalador instala aproximadamente 100 000 bytes y, por consiguiente, debe aumentar la estimación de la longitud total final de la barra de progreso en 100 000 tics.

    Nota:

    Para calcularlo dinámicamente, la acción personalizada debe contener una sección que se ejecuta inmediatamente durante la generación de scripts. La cantidad de tics que notifica la acción personalizada de ejecución diferida debe coincidir con al número de tics agregados al recuento total de tics mediante la acción de ejecución inmediata. Si no es así, el tiempo restante que indica el control de texto TimeRemaining no será exacto.

     

  4. Separe la acción personalizada en dos secciones de código: una que se ejecuta durante la fase de generación de scripts y otra que se ejecuta durante la fase de ejecución de la instalación. Puede hacerlo con dos archivos, o bien puede usar solo uno condicionando el modo de ejecución del instalador. En el siguiente ejemplo se utiliza un archivo y se comprueba el estado de la instalación. Las secciones del ejemplo están condicionadas para ejecutarse en función de si el instalador está en la fase de ejecución o de generación de scripts de la instalación.

  5. La sección que se ejecuta durante la generación de scripts debe incrementar la estimación de la longitud total final de la barra de progreso en el número total de tics de la acción personalizada. Para ello, se envía un mensaje del progreso de ProgressAddition.

  6. La sección que se ejecuta durante la fase de ejecución de la instalación debe configurar el texto del mensaje y las plantillas que informan al usuario sobre lo que hace la acción personalizada y para dirigir al instalador en la actualización del control ProgressBar. Por ejemplo, informe al instalador para que adelante la ProgressBar un incremento y envíe un mensaje de progreso explícito con cada actualización. Lo habitual es que si la acción personalizada está instalando algo, haya un bucle en esta sección. Con cada pasada por este bucle, el instalador puede instalar un elemento de referencia, como una clave de Registro, y actualizar el control ProgressBar

  7. Agregue una acción personalizada de ejecución inmediata al paquete de Windows Installer. Esta acción personalizada informa a la barra de progreso cuánto debe avanzar durante las fases de adquisición y generación de scripts de la instalación. Para el ejemplo siguiente, el origen es el archivo DLL creado mediante la compilación del código de ejemplo y el destino es el punto de entrada CAProgress.

  8. Agregue una acción personalizada de ejecución diferida al paquete de Windows Installer. Esta acción personalizada completa los pasos de la instalación real e informa a la barra de progreso de cuánto debe avanzar la barra en el momento en que el instalador ejecuta el script de instalación. Para el ejemplo siguiente, el origen es el archivo DLL creado mediante la compilación del código de ejemplo y el destino es el punto de entrada CAProgress.

  9. Programe ambas acciones personalizadas entre InstallInitialize e InstallFinalize en la tabla InstallExecuteSequence. La acción personalizada diferida debe programarse inmediatamente después de la acción personalizada de ejecución inmediata. El instalador no ejecutará la acción personalizada diferida hasta que se ejecute el script.

En el ejemplo siguiente se muestra cómo se puede agregar una acción personalizada a la barra de progreso. El origen de ambas acciones personalizadas es el archivo DLL creado mediante la compilación del código de ejemplo y el destino de ambas acciones personalizadas es el punto de entrada, CAProgress. Este ejemplo no realiza cambios en el sistema, pero opera la barra de progreso como si instalara 10 elementos de referencia de un tamaño aproximado de 10 000 bytes. El instalador actualiza el mensaje y la barra de progreso cada vez que instala un elemento de referencia.

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