Share via


Instalación a petición de juegos

En este artículo técnico se describen dos técnicas, la instalación a petición y la instalación en segundo plano, mediante Windows Installer. Los juegos pueden utilizar estas técnicas de instalación para proporcionar una experiencia de juego mejor y más agradable a los jugadores reduciendo el tiempo de instalación.

Información general

La instalación ha sido un elemento de las aplicaciones basadas en equipos durante mucho tiempo. La mayoría de las aplicaciones actualmente requieren que se instalen en el disco duro local del usuario antes de poder usarlas. Los juegos de ordenador no son ninguna excepción; cuando un consumidor compra un juego de Microsoft Windows e intenta ejecutarlo, primero debe pasar por un proceso de instalación que copia los archivos necesarios del disco del juego en el disco duro. Este proceso de instalación suele ser largo y puede tardar hasta una hora en completarse. El tiempo de instalación es un factor que hace que los juegos de consola sean más deseables que los juegos basados en ordenador para algunos jugadores, ya que pueden jugar al juego de consola inmediatamente después de insertar el disco. La tecnología que se describe en este artículo intentará solucionar este inconveniente reduciendo drásticamente el tiempo de instalación.

Tradicionalmente, los juegos requieren que todos o la mayoría de los archivos se instalen antes de iniciarse. Para lograr la instalación a petición, los recursos del juego deben ser modulares; es decir, el desarrollador debe dividir los recursos de la aplicación (gráficos, audio, etc.) en componentes. Cada componente es un conjunto de recursos que se pueden instalar o quitar como una unidad. Una vez hecho esto, el desarrollador del juego define una o varias características, normalmente una o varias por nivel o zona. Cada característica de una aplicación especifica un conjunto de componentes necesario para ejecutar esa característica concreta. Cuando se instala una aplicación, sus características se pueden marcar como "instaladas" (componentes copiados en el disco duro local en el momento de la instalación) o "anunciadas" (componentes copiados en el disco duro local después de la instalación inicial cuando la aplicación usa esa característica). Un desarrollador de juegos puede reducir el tiempo de instalación diseñando el juego para que se inicie y ejecute con un conjunto mínimo de características instaladas. El resto de sus características se pueden marcar como anunciadas e instaladas a petición cuando la aplicación realmente necesite usar las funcionalidades que proporcionan esas características.

Los juegos pueden llamar a Windows Installer para instalar una característica determinada que puede que no se haya instalado. Para que la instalación aparezca en segundo plano, se puede usar un subproceso de trabajo para realizar las llamadas al instalador mientras el subproceso principal sigue controlando la lógica del juego y representando la pantalla. Esto minimiza la interrupción del juego que produce la instalación. El juego puede iniciar la instalación en cualquier momento. Sin embargo, dado que la instalación consume ciclos de procesador, por lo general no es una buena idea realizar la instalación cuando el subproceso principal necesita imperiosamente potencia de procesamiento, como cuando el usuario está en medio de la acción. Por ejemplo, un buen momento para realizar la instalación puede ser cuando el usuario está en el menú del juego, el juego está en pausa o minimizado, o el usuario está viendo el vídeo de introducción o las escenas de cinemática.

Compatibilidad con la aplicación de revisiones

La mayoría de los juegos actualmente deben actualizarse incluso después de enviarse, a medida que se corrigen errores y se agregan nuevas características. La actualización a menudo requiere la aplicación de revisiones, lo cual normalmente es un procedimiento sencillo para los juegos. Dado que todos los archivos necesarios se instalan en el disco duro del usuario, aplicar revisiones a un juego implica copiar los archivos revisados en el disco duro, sobrescribiendo los archivos existentes. Cuando se emplea la instalación a petición, no todos los archivos se instalan y copian en el momento de aplicar las revisiones. Por lo tanto, el aplicador de revisiones no puede escribir simplemente archivos actualizados en la carpeta del juego.

Windows Installer tiene características para aplicar revisiones a aplicaciones que usan la instalación a petición. Al aplicar una revisión, el instalador almacena en caché la revisión en el sistema. Esta característica funciona bien para las revisiones con pocas diferencias. Los archivos publicados originalmente ya no necesitan estar en el disco en el momento de aplicar las revisiones, por lo que esos archivos se pueden anunciar. Más adelante, cuando la aplicación se ejecuta y necesita acceder a los archivos, el instalador instala la versión más reciente de esos archivos copiando la versión publicada originalmente desde el soporte físico (por ejemplo, CD) y aplicando la revisión después de leer los datos de revisión guardados.

Ejemplo del SDK InstallOnDemand

En el ejemplo de instalación a petición de juegos se muestran las técnicas de instalación a petición que se describen en este artículo. A diferencia de otros ejemplos, la instalación a petición de juegos no se puede ejecutar directamente desde el explorador de ejemplo. Dado que el ejemplo usa Windows Installer para administrar su instalación, debe incluirse en la base de datos del instalador de las aplicaciones instaladas.

Para iniciar el ejemplo

  1. Use el vínculo Instalar proyecto en el explorador de ejemplo para copiar los archivos del ejemplo en una carpeta.
  2. Haga doble clic en InstallOnDemand.msi para instalar el ejemplo.
  3. Seleccione Instalación típica.
  4. Para iniciar el ejemplo, ejecute InstallOnDemand.exe en la carpeta instalada (normalmente Archivos de programa\InstallOnDemand) o inicie desde el menú Inicio\Programas.

InstallOnDemand.msi es una base de datos reconocida por el instalador. Define todo el proceso de instalación: la estructura del directorio, lo que se va a copiar y lo que no, qué recursos se copiarán juntos, qué valores del Registro se van a escribir, qué métodos abreviados se van a crear, etc.

Cuando se inicia, el ejemplo reproduce una secuencia de introducción. El jugador puede terminar y entrar en el menú principal presionando la tecla ESC. Después de la introducción, el jugador puede empezar un nuevo juego escribiendo un nombre de personaje y desplazándose por las estadísticas. Antes de que el ejemplo empiece a reproducir la secuencia de introducción, llama a una función del instalador para comprobar si está instalada la característica de nivel 1. Si no se ha instalado la característica de nivel 1, el ejemplo usa un subproceso en segundo plano para pedir al instalador que instale el juego, mientras que el subproceso principal está haciendo otra cosa (como reproducir la secuencia de introducción, representar el menú o interactuar con el jugador sobre la creación de personajes). La experiencia es diferente de la instalación tradicional de un juego en que el usuario está ocupado en el juego (viendo la introducción o creando un nuevo personaje) mientras la instalación está en curso. Una vez que el jugador haya terminado de crear un personaje, el ejemplo carga los recursos del nivel 1.

En el lado derecho de la pantalla de ejemplo hay cinco botones marcados como "Nivel de reproducción 1" a "Nivel de reproducción 5". Estos botones simulan la finalización por parte del jugador del nivel actual y el paso al siguiente. Cuando se hace clic en uno de estos botones, aparece una pantalla de estadísticas que muestra información sobre el nivel que acaba de terminar. El ejemplo también tarda este tiempo en pedir al instalador que compruebe e instale el siguiente nivel, si aún no está instalado. La instalación se produce mientras el reproductor lee la pantalla de estadísticas, de modo que cuando el usuario hace clic en Aceptar para entrar en el siguiente nivel, todos los recursos del nivel están instalados y listos para cargarse.

Características y componentes del ejemplo

Tradicionalmente, los juegos requieren que todos o la mayoría de los archivos se instalen antes de iniciarse. Para lograr la instalación a petición, los recursos del juego deben ser modulares; es decir, el desarrollador debe dividir los recursos de la aplicación (gráficos, audio, etc.) en componentes. Cada componente es un conjunto de recursos que se pueden instalar o quitar como una unidad. Una vez hecho esto, el desarrollador del juego define una o varias características, normalmente una o varias por nivel o zona. Cada característica de una aplicación especifica un conjunto de componentes necesario para ejecutar esa característica concreta. Cuando se instala una aplicación, sus características se pueden marcar como "instaladas" (componentes copiados en el disco duro local en el momento de la instalación) o "anunciadas" (componentes copiados en el disco duro local cuando la aplicación usa esa característica más tarde). Un desarrollador de juegos puede reducir el tiempo de instalación diseñando el juego para que se inicie y empiece a ejecutarse con un conjunto mínimo de características instaladas. El resto de sus características se pueden marcar como anunciadas e instaladas a petición cuando la aplicación realmente necesite usar las funcionalidades que proporcionan esas características.

En la tabla siguiente se enumeran las seis características de nivel superior que define el ejemplo.

Nombre de la característica Funcionalidad Componentes Files
Principal Incluye los recursos que se necesitan en todo momento, independientemente del nivel. Estos recursos son: archivo ejecutable de ejemplo, elementos multimedia que requiere la secuencia de introducción y la pantalla de carga, y un archivo .fx que controla toda representación en el ejemplo. Principal InstallOnDemand.exe, InstallOnDemand.fx, Loading.bmp, Level.x
Principal (igual que antes) CoreUI Media\UI\dxutcontrols.dds, Media\UI\DXUTShared.fx, Media\UI\arrow.x
Principal (igual que antes) CoreMisc Media\Misc\seafloor.x, Media\Misc\seafloor.bmp
Principal (igual que antes) CoreSpeeder Media\PRT Demo\LandShark.x, Media\PRT Demo\speeder_diff.jpg
Principal (igual que antes) CoreReg No disponible (valor del Registro)
Level1 Proporciona los recursos que usa el nivel 1. Level1 Level1.jpg
Level1 (igual que antes) L1Skybox Media\Light Probes\galileo_cross.dds
Level2 Proporciona los recursos que usa el nivel 2. Level2 Level2.jpg
Level2 (igual que antes) L2Skybox Media\Light Probes\grace_cross.dds
Level3 Proporciona los recursos que usa el nivel 3. Level3 Level3.jpg
Level3 (igual que antes) L3Skybox Media\Light Probes\rnl_cross.dds
Level4 Proporciona los recursos que usa el nivel 4. Level4 Level4.jpg
Level4 (igual que antes) L4Skybox Media\Light Probes\stpeters_cross.dds
Level5 Proporciona los recursos que usa el nivel 5. Level5 Level5.jpg
Level5 (igual que antes) L5Skybox Media\Light Probes\uffizi_cross.dds

 

Las características Level1 a Level5 tienen características secundarias adicionales que contienen archivos que el ejemplo no usa directamente. Estos archivos de características secundarias se han agregado para que la instalación tarde más tiempo. Esto se hace para ilustrar la operación de instalación en curso que se ejecuta en segundo plano mientras se ejecuta el ejemplo.

La siguiente tabla enumera las características secundarias.

Característica Características secundarias Files
Level1 L1PH1, L1PH2, L1PH3, L1PH4, L1PH5 Level1 Placeholder Data\L1PH1.dat Level1 Placeholder Data\L1PH2.dat Level1 Placeholder Data\L1PH3.dat Level1 Placeholder Data\L1PH4.dat Level1 Placeholder Data\L1PH5.dat
Level2 L2PH1, L2PH2, L2PH3, L2PH4, L2PH5 Level2 Placeholder Data\L2PH1.dat Level2 Placeholder Data\L2PH2.dat Level2 Placeholder Data\L2PH3.dat Level2 Placeholder Data\L2PH4.dat Level2 Placeholder Data\L2PH5.dat
Level3 L3PH1, L3PH2, L3PH3, L3PH4, L3PH5 Level3 Placeholder Data\L3PH1.dat Level3 Placeholder Data\L3PH2.dat Level3 Placeholder Data\L3PH3.dat Level3 Placeholder Data\L3PH4.dat Level3 Placeholder Data\L3PH5.dat
Level4 L4PH1, L4PH2, L4PH3, L4PH4, L4PH5 Level4 Placeholder Data\L4PH1.dat Level4 Placeholder Data\L4PH2.dat Level4 Placeholder Data\L4PH3.dat Level4 Placeholder Data\L4PH4.dat Level4 Placeholder Data\L4PH5.dat
Level5 L5PH1, L5PH2, L5PH3, L5PH4, L5PH5 Level5 Placeholder Data\L5PH1.dat Level5 Placeholder Data\L5PH2.dat Level5 Placeholder Data\L5PH3.dat Level5 Placeholder Data\L5PH4.dat Level5 Placeholder Data\L5PH5.dat

 

Durante la instalación, la característica principal debe marcarse como "instalada" y todas las demás características deben marcarse como "anunciadas". Al instalar solo una característica en lugar de seis, el tiempo que el jugador debe esperar hasta que se inicia el juego se reduce significativamente.

Instalación

Windows Installer proporciona un mecanismo para que una aplicación solicite que se instale una característica anunciada. Sin embargo, el mecanismo es una llamada sincrónica de interfaz de programación de aplicaciones (API), lo que significa que la aplicación tiene que esperar dentro de la llamada hasta que se complete la instalación. Para lograr la instalación en segundo plano, se requiere un subproceso de trabajo para que el subproceso principal de la aplicación pueda realizar otras tareas importantes, como la representación en la pantalla para seguir proporcionando comentarios visuales al jugador.

En el ejemplo, hay tres estados de instalación que se producen durante la ejecución del ejemplo: instalación activa, instalación pasiva y sin instalación.

  • La instalación activa es una solicitud iniciada por el ejemplo cuando necesita acceder o cargar los recursos que una o varias características proporcionan. El ejemplo hace esto cuando no puede continuar hasta que se instale el recurso.
  • La instalación pasiva se inicia cuando el ejemplo no está realizando ninguna tarea crítica, como cuando el jugador está en un menú o viendo una escena de cinemática. Cuando este es el caso, el subproceso de trabajo comprueba si alguna característica del ejemplo todavía se anuncia. Si puede encontrar una, llama al instalador para instalar esa característica. Este proceso se repite hasta que se instalan todas las características del ejemplo. Básicamente, la instalación pasiva utiliza ciclos de procesador adicionales para realizar la instalación en segundo plano cuando es menos intrusivo para el ejemplo principal.
  • No se produce ninguna instalación cuando el jugador participa activamente en el juego; esto evita una caída de la velocidad de fotogramas que interrumpiría la experiencia del usuario.

En el ejemplo, se define una clase CMsiUtil para controlar todas las tareas relacionadas con la instalación. Básicamente, CMsiUtil usa un subproceso de trabajo que invoca al instalador para instalar las características del ejemplo en un bucle. La clase tiene dos colas que almacenan las solicitudes de instalación: una cola de prioridad alta para la instalación activa y una cola de prioridad baja para la instalación pasiva. Durante la inicialización, la clase enumera todas las características del producto y las agrega a la cola de instalación pasiva. Dado que todo el producto se pone en cola de esta manera, todo el producto se instalará finalmente si el ejemplo tiene suficientes ciclos de procesador libres.

Cuando el ejemplo necesita solicitar una instalación activa, el ejemplo puede llamar a CMsiUtil::UseFeatureSet() y pasar el nombre de la característica de nivel superior. UseFeatureSet() pondrá la característica solicitada y todas sus características secundarias en la cola de instalación activa para que el subproceso de trabajo pueda instalarlas.

Al ejecutar una solicitud de instalación, el subproceso de trabajo comprobará la cola de instalación activa, así como la cola de instalación pasiva para ver si alguna de ellas tiene solicitudes adicionales. Cada vez que el subproceso encuentre una solicitud, llamará a la API del instalador para realizar la instalación real. Una vez que ambas colas estén vacías, el subproceso de trabajo pasará al modo de suspensión con una llamada a WaitForSingleObject. Dado que todo el producto se coloca en la cola de instalación pasiva durante la inicialización, una cola vacía implica que se ha instalado todo el producto.

El ejemplo llama a CMsiUtil::EnablePassiveInstall() para habilitar o deshabilitar la instalación pasiva. EnablePassiveInstall(true) incrementa el recuento de habilitaciones de la instalación pasiva y EnablePassiveInstall(false) lo disminuye. Si el recuento de habilitaciones es mayor que 0, la clase procesará la cola de instalación pasiva. El ejemplo permite la instalación pasiva cuando se cumple cualquiera de las siguientes condiciones:

  • El usuario está viendo la secuencia de introducción inicial.
  • El usuario está recorriendo el menú de ejemplo.
  • El usuario está viendo las estadísticas al final de un nivel.
  • La aplicación de ejemplo deja de ser el foco y pasa al segundo plano.

A continuación se enumeran los métodos de CMsiUtil:

Method Descripción
AbortAllRequests Hace que la instalación actual se anule y vacía la cola de solicitudes de instalación activa.
AbortCurrentRequest Hace que la instalación en curso se anule. A continuación, el subproceso de trabajo procesa la siguiente solicitud de la cola, si existe.
EnablePassiveInstall Incrementa o disminuye el recuento de habilitaciones de la instalación pasiva. En el ejemplo se usa esta llamada para controlar cuándo se puede realizar la instalación pasiva y cuándo no.
GetCurrentFeatureName Devuelve el nombre de la característica que se está instalando activamente.
GetFeatureProgress Devuelve la posición del tic actual de la característica que se está instalando.
GetFeatureProgressMax Devuelve el número máximo de tics de progreso de la característica que se está instalando.
Obtener último error Use este método para recuperar el código devuelto de la solicitud de instalación anterior.
GetPassiveProgress Devuelve la posición del tic de la barra de progreso para la instalación pasiva.
GetPassiveProgressMax Devuelve la posición actual del tic y el número máximo de tics de la instalación pasiva. Juntos, el ejemplo puede usarlos para mostrar el progreso general de la instalación pasiva.
GetProgress Devuelve la posición del tic de la barra de progreso para la instalación del conjunto de características activo. Esto se usa cuando el ejemplo representa la barra de progreso de la instalación. Dado que Windows Installer solo proporciona información de progreso de la característica que se está instalando, el método divide la barra de progreso entre las características solicitadas para que el usuario siga viendo toda la instalación como una tarea.
GetProgressMax Devuelve el número máximo de tics de la barra de progreso para la instalación del conjunto de características activo. Esto se usa cuando el ejemplo representa la barra de progreso de la instalación.
Inicialización Inicializa la clase con el identificador único global (GUID) del producto. Este método también enumera todas las características de la aplicación que se han anunciado pero que aún no están instaladas y las coloca en la cola de instalación pasiva para configurar la instalación pasiva.
IsInstallInProgress Use este método para averiguar si se está procesando una instalación activa.
UseFeature Método privado llamado por UseFeatureSet. Comprueba si una característica está instalada. Si está instalada la característica solicitada, el método vuelve. Si la característica aún no está instalada (anunciada), el método pone en cola una nueva solicitud de instalación activa para el subproceso de trabajo y, a continuación, vuelve. Identificador de eventos opcional que se indicará cuando se complete la instalación solicitada.
UseFeatureSet Lo llama el ejemplo cuando necesita acceder a las funcionalidades proporcionadas por una característica determinada o cualquiera de sus características secundarias. El método enumera todas las características del ejemplo y llama a UseFeature() para las características secundarias de la característica raíz especificada. El ejemplo puede pasar un identificador de evento que se indicará cuando se instale todo el conjunto de características. Dado que todas las características están instaladas como un conjunto, el identificador se especifica para la última característica puesta en cola por UseFeature() en lugar de cada característica, de modo que el ejemplo reciba una notificación una vez instaladas todas las características solicitadas.
UseProduct Pone en cola una solicitud de instalación activa para que el subproceso de trabajo llame al instalador para realizar una instalación completa del producto. Identificador de eventos opcional que se indicará cuando se complete la instalación solicitada.

 

Limitación

La versión actual del instalador no está diseñada para que varios subprocesos accedan simultáneamente. Por lo tanto, si el subproceso de trabajo llama al instalador, el subproceso principal no debe llamarlo. Un ejemplo de esta limitación se produce en el ejemplo cuando el subproceso principal solicita una característica y, a continuación, vuelve a solicitar la misma característica antes de que el subproceso de trabajo complete la instalación. La segunda solicitud llama a MsiQueryFeatureState() para averiguar si la característica solicitada ya está instalada, ya que, en ocasiones, el instalador puede indicar que la característica está completamente instalada cuando, en realidad, el subproceso de trabajo sigue copiando los archivos.

Afortunadamente, hay una solución fácil para esto. CMsiUtil comprobará si el subproceso de trabajo está instalando una característica antes de llamar a funciones como MsiQueryFeatureState() o MsiUseFeature() para solicitar el estado de instalación de la característica en cuestión. Tenga en cuenta que esta limitación también puede convertirse en un problema en otro lugar.

La aplicación de revisiones puede afectar al funcionamiento de la instalación a petición en un equipo del usuario final. Aplicar una revisión que solo contenga datos que hayan cambiado desde la versión anterior puede requerir que se instale la versión anterior del archivo actualizado para aplicar la diferencia. En esta situación, la revisión debe solicitar que el instalador instale las características anunciadas afectadas antes de aplicar la revisión al juego.

El ejemplo se instala iniciando InstallOnDemand.msi porque supone que Windows Installer está presente en el equipo. Si el instalador no está presente, los archivos .msi no se reconocerán e iniciarlos no funcionará. Para solucionar este problema, una aplicación debe usar un programa de instalación para realizar la tarea. Este programa debe comprobar primero si el instalador está presente y, si es así, su versión. Si la versión no cumple el requisito de la aplicación, el programa de instalación debe instalar Windows Installer y, a continuación, iniciar el archivo .msi. Este procedimiento se conoce como inicio. Las aplicaciones suelen asignar el nombre Setup.exe al programa de instalación del inicio. El ejemplo no controla el inicio. No obstante, puede encontrar información más completa sobre el inicio en Windows Installer.

Los desarrolladores también deben prestar atención al tamaño de cada característica de sus juegos. Al cancelar una instalación en curso, el instalador restaura el equipo al estado anterior a la instalación. Esto significa que la instalación de la característica se deshace completamente y no se produce ninguna instalación parcial de características. Una característica grande requiere más tiempo para instalarse, lo que aumenta la probabilidad de que la instalación se interrumpa y cancele o que la instalación interfiera con la aplicación principal. Un ejemplo sería habilitar la instalación pasiva cuando el usuario abre el menú del juego en medio de la partida. Si una característica se está instalando y el usuario vuelve a jugar, el juego puede hacer una de estas dos cosas: permitir que se complete la instalación pasiva o cancelarla. Una característica grande no encajaría bien en ninguno de esos modelos. Si el juego permite completar la instalación grande, esta puede dificultar el rendimiento de la representación del juego durante mucho tiempo. Por el contrario, si el juego cancela la instalación, el usuario deberá permanecer en el menú durante mucho tiempo antes de volver al juego. Los desarrolladores deben encontrar el tamaño de característica equilibrado que funcione mejor para sus juegos individuales.