20
InstallShield Express InstallShield Express (ISX) es una aplicación que genera instaladores para nuestros programas. Estos instaladores pueden copiar archivos al disco rígido, crear o modificar entradas en el registro del sistema, crear o modificar archivos .ini, instalar la BDE... y todo con una interfaz amigable para el usuario final. Los instaladores generados con InstallShield Express utilizan el servicio de instalación de Windows, y tienen el aspecto y comportamiento comunes en los instaladores comerciales: La imagen pertenece al instalador que construiremos en este artículo como ejemplo En el presente artículo haré una pasada rápida por todos los pasos necesarios para crear un instalador, mientras construimos un instalador funcional para una aplicación de ejemplo que se instala con Delphi llamada MastApp. Este escrito está en pañales, hay varios puntos que solamente comento y sigo de largo porque no se usan en el ejemplo; la intención es tener una guía para los pasos básicos. En futuras revisiones trataré de dar otros ejemplos más complejos, como ser un instalador que no use la BDE y tenga que instalar el servidor Firebird, o uno que habilite la opción de actualización automática… se escuchan sugerencias. La versión que viene con Delphi es una versión especial para ser distribuida con el compilador de Borland; se restringe el acceso a ciertas funciones avanzadas, no se puede cambiar –al menos no fácilmente- el idioma de la interfaz, etc. Pero aún así los instaladores generados son muy profesionales y se crean con poco esfuerzo. La versión que estudiaremos aquí es la 3.5 que viene con Delphi 7. No obstante, la interfaz y por lo tanto las operaciones son muy similares a las de la version 3 que acompaña a Delphi 6. La pantalla inicial de ISX es una bienvenida general a la aplicación:

Install Shield Express

Embed Size (px)

DESCRIPTION

Guía para la Creación de Programa Instalador de Aplicaciones

Citation preview

Page 1: Install Shield Express

InstallShield Express

InstallShield Express (ISX) es una aplicación que genera instaladores para nuestros programas. Estos instaladores pueden copiar archivos al disco rígido, crear o modificar entradas en el registro del sistema, crear o modificar archivos .ini, instalar la BDE... y todo con una interfaz amigable para el usuario final. Los instaladores generados con InstallShield Express utilizan el servicio de instalación de Windows, y tienen el aspecto y comportamiento comunes en los instaladores comerciales:

La imagen pertenece al instalador que construiremos en este artículo como ejemplo

En el presente artículo haré una pasada rápida por todos los pasos necesarios para crear un instalador, mientras construimos un instalador funcional para una aplicación de ejemplo que se instala con Delphi llamada MastApp.

Este escrito está en pañales, hay varios puntos que solamente comento y sigo de largo porque no se usan en el ejemplo; la intención es tener una guía para los pasos básicos. En futuras revisiones trataré de dar otros ejemplos más complejos, como ser un instalador que no use la BDE y tenga que instalar el servidor Firebird, o uno que habilite la opción de actualización automática… se escuchan sugerencias.

La versión que viene con Delphi es una versión especial para ser distribuida con el compilador de Borland; se restringe el acceso a ciertas funciones avanzadas, no se puede cambiar –al menos no fácilmente- el idioma de la interfaz, etc. Pero aún así los instaladores generados son muy profesionales y se crean con poco esfuerzo.

La versión que estudiaremos aquí es la 3.5 que viene con Delphi 7. No obstante, la interfaz y por lo tanto las operaciones son muy similares a las de la version 3 que acompaña a Delphi 6.

La pantalla inicial de ISX es una bienvenida general a la aplicación:

Page 2: Install Shield Express

Daré aquí un repaso a la creación de un instalador nuevo usando como ejemplo una aplicación que viene con Delphi: MastApp, que se instala por defecto en el directorio $(Delphi)\demos\db\mastapp. Esta aplicación utiliza la BDE para acceder a los datos de tablas Paradox, por lo que el instalador tendrá que instalar la BDE, configurarla, crear el alias DBDEMOS que utiliza la aplicación apuntando al directorio adonde se copien los archivos de las tablas, y copiar las tablas y demás archivos necesarios (como el archivo .hlp de ayuda).

Comenzaremos con la opción 'Create a new project', que nos pedirá el nombre del archivo de configuración de instalación a crear (a la derecha, abajo):

Page 3: Install Shield Express

Una vez que hayamos seleccionado donde poner el archivo .ism, presionamos el botón 'Create' y comenzaremos el proceso de creación propiamente dicho. La pantalla de ISX cambia para reflejar las nuevas opciones:

Page 4: Install Shield Express

El proceso de creación consta de varios pasos, indicados en el árbol de la izquierda. Cuando seleccionamos un nodo del árbol de opciones vemos en los paneles de la derecha las propiedades para ese nodo, y si es pertinente, alguna información sobre las mismas.

Información General En la imagen anterior se ven las propiedades del primer nodo (general information), en donde configuraremos la información general del proyecto. En su mayor parte son datos informativos, como el nro. de versión o el nombre del autor; pero hay un dato que es importante para la instalación, el directorio por defecto adonde se instalará la aplicación. La propiedad se denomina INSTALLDIR, y se comportará como una variable que se podrá usar en donde se nos pida un directorio… lo cual nos lleva al concepto de ‘variables de carpeta’ (folder propierties) de InstallShield. Las variables de carpeta son variables globales cuyo valor es el nombre de una carpeta de la maquina destino. Hay varias predefinidas en ISX:

Variable de carpeta Significado

SourceDir El directorio raíz adonde se localizan los archivos fuentes de la instalación

TargetDir El directorio adonde se copia el paquete del instalador de Windows, durante una instalación administrativa (se hace una copia de los archivos de la instalación para que se puedan acceder a través de una red)

InstallDir El directorio destino seleccionado para la instalación

AppDataFolder Directorio de datos de aplicación para el usuario actual

CommonFilesFolder Directorio de Archivos Comunes para el usuario actual

DesktopFolder Directorio del escritorio para el usuario actual

Page 5: Install Shield Express

Variable de carpeta Significado

FavoritesFolder Directorio de Favoritos para el usuario actual

FontsFolder Directorio de fuentes

PersonalFolder Directorio personal del usuario

ProgramFilesFolder Directorio de Archivos de Programa

ProgramMenuFolder Directorio del menú Programas para el usuario actual

SendToFolder Directorio Enviar a… para el usuario actual

StartMenuFolder Directorio del menú inicio para el usuario actual

System16Folder Directorio que contiene las DLLs de 16 bits del sistema

SystemFolder Directorio de sistema

TempFolder Directorio temporal del sistema

TemplateFolder Directorio de modelos del usuario actual

WindowsFolder Directorio adonde se instaló Windows

WindowsVolume Disco adonde se instaló Windows

También existen algunas propiedades predefinidas, que almacenarán datos útiles de la instalación:

Propiedad Contenido

CompanyName No es un directorio, sino el nombre de la organización del usuario que ejecuta la instalación. Se toma del cuadro de diálogo de Información del Usuario

UserName Nombre del usuario que ejecuta la instalación, tomado del cuadro de diálogo de información del usuario

ProductCode El GUID (Identificador global) de esta versión del producto. Debe ser diferente para distintas versiones. Se ingresa entre las propiedades del primer nodo, General Information

ProductName Nombre del producto a instalar, tomado de las propiedades del nodo General Information

ProductVersion Versión del producto a instalar, tomado de las propiedades del nodo General Information

Estas propiedades se pueden usar como variables en los lugares donde se necesite el nombre de una carpeta, sin olvidar que representan valores de la máquina destino de la instalación. Para usarlas, se indica el nombre de la propiedad entre corchetes. Un ejemplo se ve en el valor por defecto de la propiedad INSTALLDIR: [ProgramFilesFolder] \Your Company Name\Default. La propiedad [ProgramFilesFolder] tomará el valor de la carpeta marcada como ‘Archivos de programa’ en la máquina destino de la instalación (leyéndolo del registro del sistema). La parte siguiente (\Your Company Name\Default) es una cadena literal, que tendremos que cambiar.

En nuestro ejemplo queremos que la aplicación MastApp se instale por defecto en ‘\Archivos de programa\MastApp’, por lo que en la propiedad InstallDir del nodo de Información general pondremos [ProgramFilesFolder]\MastApp Con eso basta.

Page 6: Install Shield Express

Hay otra propiedad de carpeta en el nodo de Información General: DATABASEDIR. Esta variable existe para permitir indicar un directorio adonde poner la base de datos, diferente del directorio de instalación. Note que por defecto se propone una carpeta ‘Database’ dentro de la carpeta de instalación del programa.

El resto de las propiedades de este nodo son descriptivas y bastante explícitas, por lo que no me detendré a explicar cada una.

Perfiles El siguiente nodo (Features) permite definir los perfiles de instalación. Los perfiles son grupos de características (archivos, módulos, etc) con un nombre. En esta pantalla solamente se definen, junto con sus propiedades; luego asociaremos distintos perfiles a cada tipo de instalación.

El usuario final puede seleccionar los perfiles en forma individual en la instalación personalizada.

Tipos de instalación Una vez que tenemos definidos los perfiles, podemos pasar a declarar los tipos de instalación que vamos a permitir (por ejemplo: Típica, Completa, Personalizada). El siguiente nodo en el árbol de la izquierda (Setup types) nos permite definir los tipos de instalación y asociar a cada tipo los perfiles que correspondan:

Page 7: Install Shield Express

Hemos definido tres tipos de instalación: Típica, Cliente solamente y Personalizada. Cada una tiene asociados ciertos perfiles; en la imagen anterior se ve que la instalación típica instalará todas características definidas.

La instalación ‘Cliente solamente’ instalará la aplicación cliente (perfil Cliente), los archivos de ayuda (Perfil Always Install), y la BDE (perfil BDE). No se instalarán los archivos de bases de datos (perfil Base de datos), asumiendo que están en un servidor de archivos que se accede a través de la red.

Page 8: Install Shield Express

La instalación personalizada tiene marcados todos los perfiles por defecto, pero el usuario podrá seleccionar los que desee en el momento de la instalación real.

Actualizaciones El siguiente nodo (upgrade paths) nos permite indicar al instalador las posibilidades de actualización de una versión anterior de nuestro programa.

En esta pantalla definimos los parámetros de búsqueda de versiones anteriores de la aplicación. Cuando se encuentra una versión que cumpla con los criterios especificados, se reemplazarán sus archivos automáticamente por los nuevos. Hay que tener en cuenta un par de consideraciones:

• El código de producto y la versión deben ser ser distintos de las versiones anteriores de la aplicación.

• El código de actualización (upgrade code) debe ser el mismo en todas las versiones

La actualización que se puede definir con ISX es completa, es decir que la instalación anterior es reemplazada totalmente por la nueva. Las versiones más avanzadas de InstallShield (como la Developer) brindan la posibilidad de definir actualizaciones a nivel de archivos individuales.

Archivos El nodo siguiente es files (archivos). Aquí definimos cada archivo que compone la entrega, y a qué carpeta irá a parar en el destino… para cada perfil.

Page 9: Install Shield Express

Comenzamos seleccionando el perfil que vamos a configurar, en la lista de la parte superior (‘Feature’):

A continuación hacemos visible el directorio destino de los archivos, normalmente usando las variables de carpeta de las que hablamos antes, en el árbol de directorios inferior.

Podemos mostrar otras carpetas predefinidas

como variables usando el menú contextual de este panel (‘Show predefined

folder’). Si lo que deseamos es colocar los archivos en una carpeta fija del equipo destino, podemos agregar el

nombre con la opción ‘Add’ del menú contextual.

Nota: las carpetas indicadas se crearán si no existen en el equipo destino de la instalación.

Ahora sí, seleccionamos y agregamos los archivos que componen el perfil a la carpeta seleccionada como destino (arrastrando de la lista de archivos superior a la inferior). En nuestro ejemplo, los perfiles serán compuestos como sigue:

• Always install: nada

Page 10: Install Shield Express

• Base de datos: archivos que conforman la base de datos, del directorio ‘\Arhivos de programa\Archivos comunes\Borland Shared\data\’: orders.*, customer.*, items.*, parts.*, employee.*, vendors.*, NextOrd.*, NextCust.*, NextItem.*. Uso el asterisco aquí para indicar los distintos archivos que se crean en Paradox para cada tabla: .db, .px, .x??, .y??, .mb, .val.

Destino: [DatabaseDir]

• Cliente solamente: ejecutable (mastapp.exe), archivo de ayuda (mastapp.hlp)

Destino: [InstallDir]

• BDE: nada aquí; en un paso posterior agregaremos un módulo precompilado

En la imagen siguiente se ven los archivos correspondientes a la tabla Customer, ya colocados en la carpeta [DatabaseDir]:

Nota: los archivos quedan enlazados en forma estática al directorio origen; es decir que en el momento de generar el instalador, los archivos a incluir se buscarán en los directorios originales de donde se arrastraron. En el ejemplo, el archivo customer.db se buscará en c:\archivos de programa\archivos comunes\borland shared\data. Si movemos estos archivos a otro directorio, tendremos que eliminarlos de la lista y volverlos a arrastrar desde la nueva ubicación.

El paso siguiente, Files and features, permite reubicar los archivos dentro de los perfiles:

Page 11: Install Shield Express

Simplemente arrastre los archivos a los perfiles que desee.

En nuestro ejemplo ya tenemos todo bien asignado, por lo que este seguimos adelante sin hacer nada.

Módulos precompilados El siguiente paso permite la especificación de módulos precompilados para agregarlos a la distribución. Los módulos precompilados son pequeños instaladores en si mismos, compilados de manera que se puedan agregar fácilmente a una distribución. El ejemplo más conocido es la BDE: todos los archivos que la componen, más las instrucciones de configuración comunes, están empaquetados en un módulo que se puede agregar al instalador en este paso.

Page 12: Install Shield Express

Los módulos son archivos con extensión .msm; hay muchos de ellos en Internet, que permiten construir instaladores en forma modular. Por ejemplo, en la siguiente dirección http://www.mwasoftware.co.uk/firebird se pueden encontrar módulos precompilados para instalar el servidor Firebird. Para que ISX los reconozca debemos copiar los archivos .msm al directorio modules/i386 dentro de la carpeta de instalación de InstallShield Express.

La versión de InstallShield Express que viene con Delphi incluye módulos para instalar los paquetes de ejecución de los componentes de estándar, además de la BDE completa. Para nuestro ejemplo, agregaremos el módulo de la BDE marcando la casilla que está junto al nombre.

En ese momento se ejecuta un asistente para la configuración de la BDE en la máquina destino. Es aquí donde definimos los alias a ser creados en la máquina destino, los controladores que se instalarán, etc.

La configuración de la BDE se almacenará en un archivo .ini; el asistente comenzará justamente preguntando por este archivo. Si tenemos uno ya creado, podemos seleccionarlo con la segunda opción; caso contrario, indicamos un nombre de archivo (con la ruta completa, de la máquina origen) que será creado por el asistente.

En el ejemplo he creado un nuevo archivo de configuración llamado BDEConf.ini, en el directorio c:\temp:

Page 13: Install Shield Express

Al presionar ‘Siguiente’ se creará el archivo y nos dará la opción de configurarlo usando otro asistente. En la siguiente serie de imágenes, he indicado la creación de un alias DBDemos en la máquina destino de la instalación:

Presionamos el botón ‘Launch’ para arrancar el asistente de configuración:

Page 14: Install Shield Express

Aquí marcamos los controladores que nuestra aplicación necesita para conectar con la Base de Datos. En el ejemplo usamos Paradox, que se instala por defecto; por lo tanto no marcamos ningún controlador de la lista.

Presionamos el botón ‘Add’ para agregar la definición de un alias:

He usado la variable de carpeta [DatabaseDir] para indicar que el directorio de la máquina destino referenciado por el alias sea el mismo donde hemos copiado los archivos de datos.

El último paso es una confirmación de lo ingresado.

Para cambiar la configuración de la BDE después de la primera vez, tenemos una opción en el menú contextual de la lista de módulos.

Una vez concluida la configuración de los alias y controladores, indicamos al instalador que solamente incluya la BDE con el perfil llamado precisamente ‘BDE’, marcándolo en la lista de perfiles a la derecha (primero marcamos el prefil ‘BDE’ y luego desmarcamos ‘Always Install’; siempre tiene que haber por lo menos uno seleccionado):

Ya tenemos la configuración de la BDE, continuamos con el instalador. El siguiente nodo, ‘Dependencias’ (Dependencies) no está habilitado en la versión especial de ISX que acompaña a Delphi. En la versión completa, este paso nos permite ejecutar nuestra aplicación en un modo de comprobación de dependencias especial; ISX detectará cualquier DLL o archivo secundario utilizado y nos dará la opción de agregarlo al instalador.

El grupo siguiente de opciones sirven para configurar la máquina destino: crear accesos directos, entradas en el menú Inicio, modificar el registro, etc.

Accesos directos Una vez que se han copiado los archivos del perfil seleccionado al disco destino, es bueno crear un acceso directo (shortcut) al mismo. Los accesos directos se pueden crear en cualquier carpeta del equipo destino,

Page 15: Install Shield Express

aunque lo más común es crear uno en el menú inicio (eventualmente dentro de una nueva carpeta propia de nuestra aplicación) y otro en el escritorio. InstallShield permite crear fácilmente estos accesos directos.

Los datos del nodo shortcuts/folders muestra un nuevo árbol con sólo unas pocas carpetas de la máquina destino. A continuación va una lista de los nombres de estas carpetas y sus equivalentes en castellano:

Taskbar: barra de tareas

Start menu: menú Inicio

Programs menu: menú Programas (dentro del menú Inicio)

Startup: menú Inicio (dentro del menú Inicio). Los accesos directos creados aquí se ejecutarán automáticamente cada vez que arranque el sistema.

Send To: menú Enviar a…, que aparece normalmente en el menú contextual del explorador.

Desktop: escritorio. Los accesos creados aquí se verán en el fondo del escritorio del equipo destino.

En el ejemplo que venimos siguiendo, crearemos una nueva carpeta ‘MastApp’ en el menú Inicio, y dentro de ella crearemos un acceso directo al programa y otro al archivo de ayuda. Finalmente, crearemos también un acceso al programa en el escritorio. Todas las opciones de creación están en el menú contextual del árbol.

Comenzamos creando la carpeta dentro de la opción Programas del menú inicio. En el menú contextual del nodo ‘Programs Menu’ seleccionamos ‘New Folder’ (nueva carpeta) y le ponemos como nombre ‘MastApp’.

A continuación, creamos dentro de esa nueva carpeta los accesos al ejecutable con la opción

‘New Shortcut’ (Nuevo acceso directo) del menú contextual de la carpeta recién creada.

Vemos un cuadro de diálogo de seleccionar archivo bastante especial, ya que muestra las

carpetas del equipo destino; seleccionamos [InstallDir] y veremos dentro el icono del

ejecutable de la aplicación, como si ya estuviera instalada.

Lo seleccionamos y aceptamos el cuadro de diálogo para crear un acceso directo a ese ejecutable… en el equipo destino, una vez que esté instalado!

Una vez creado el acceso directo, si lo seleccionamos en el árbol veremos a la derecha sus propiedades, como por ejemplo la descripción, el archivo de donde obtener el icono y el índice de éste si hay varios, etc.

Page 16: Install Shield Express

Con el mismo procedimiento agregamos un acceso directo a la ayuda (el archivo .hlp), y otro acceso al ejecutable en el escritorio. El árbol debe quedar como se ve en la imagen de la izquierda.

Este paso está concluido; vamos ahora a las entradas de registro.

Modificaciones al registro Según las especificaciones de Microsoft, todas las aplicaciones deberían guardar sus datos persistentes en una rama del registro del sistema, como sigue:

HKEY_CURRENT_USER\Software\Empresa\Aplicacion

Si los valores son para todos los usuarios, entonces reemplazamos HKEY_CURRENT_USER con HKEY_LOCAL_MACHINE.

En la imagen siguiente se ven las propiedades del nodo Registry. En la parte superior tenemos el registro del equipo local, adonde estamos haciendo el instalador. Podemos seleccionar cualquiera de ellas y copiarla al portapapeles por medio del menú contextual, para pegarla en el árbol de la parte inferior que representa el registro del equipo destino, o bien crear directamente nuevas entradas en el registro destino usando como siempre el menú contextual.

Nuestro ejemplo no necesita modificaciones del registro, por lo que seguimos adelante.

Recursos ODBC En este nodo definimos los alias ODBC (DSN) a crear en el sistema destino, si es que se necesita alguno. El proceso es similar a la configuración de la BDE: seleccionamos o creamos un DSN en la parte superior, lo

Page 17: Install Shield Express

asociamos a los perfiles en los que debería crearse, y configuramos sus propiedades en la parte inferior si es necesario.

Nuestro ejemplo no utiliza ODBC para conectar con la base de datos, por lo que dejamos todo como está.

Archivos INI Otra forma común de almacenar valores persistentes de una aplicación son los archivos ini. Son archivos de texto plano, que tienen una estructura estándar entendida por Windows; hay una serie de funciones del sistema que se encargan de leer y escribir valores en este tipo de archivos.

Page 18: Install Shield Express

En la descripción del panel derecho vemos la estructura del archivo: está dividido en secciones (identificadas porque el nombre se escribe entre corchetes) y en esas secciones se colocan los diversos items a preservar siguiendo el formato <nombre>=<valor>.

Como ya es costumbre, la definición de nuevos ítems del árbol se hace a través del menú contextual; con las opciones provistas podemos crear nuevos archivos ini, y dentro de éstos nuevas secciones y dentro de éstas nuevos valores.

¿Qué pasará si en el equipo destino ya existe, digamos, un archivo .ini con el mismo nombre que el que nosotros definimos como nuevo aquí? Pues se usará ese archivo, sin borrar nada de lo existente. Si en el archivo ya existe la sección, también se utilizará sin problemas; y finalmente, si ya existe un valor, se reemplazará su valor por el que definimos en esta pantalla.

Nuevamente, nuestro ejemplo no utiliza archivos .ini por lo que pasaremos de largo hasta el siguiente nodo.

Extensiones Esta opción nos permite asociar extensiones de archivos con nuestra aplicación; de esta manera, al hacer doble click en un archivo con una de estas extensiones, se ejecutará automáticamente nuestra aplicación pasándole el nombre del archivo como parámetro.

Las propiedades de cada extensión que registremos son las mismas que se pueden configurar en las opciones avanzadas del explorador de Windows: el comando a ejecutar, los parámetros a enviar, el icono de presentación, etc. Por supuesto, para que la asociación sea útil se debe programar la aplicación de manera que acepte parámetros, por lo menos el nombre de un archivo…

¿Nuestro ejemplo? No, no se asocia con ninguna extensión, como habrán supuesto. Seguimos de largo.

La siguiente opción permite definir variables de entorno (Environment variables), pero no está habilitada en la versión que acompaña a Delphi.

Page 19: Install Shield Express

Las partes que quedan son de configuración de la interfaz del instalador: qué páginas mostrará el asistente, con qué gráfico de fondo, etc. La mayoría de las opciones de las secciones 4 y 6 están deshabilitadas en esta versión.

La opción del Servicio de actualización (Update service) permite habilitar un servicio de auto actualización para la aplicación. No lo he usado nunca así que no diré nada aquí hasta que lo haga.

Compilación Finalmente, llegamos a la parte 7: preparación para el lanzamiento. En la opción de compilación (Build your release) podemos elegir cómo queremos el instalador: por ejemplo, como un solo archivo .exe –ideal para distribuir por Internet- o como una serie de archivos listos para grabarse a un CD.

Los distintos medios listados en el árbol tienen diferentes tamaños y diferentes valores por defecto para las propiedades. ISX toma en cuenta el tamaño del medio para dividir los archivos del instalador en varios volúmenes, si es preciso.

La opción que se muestra en la imagen anterior es la de creación de un solo archivo ejecutable, que integra todo lo necesario para la instalación. Incluye las actualizaciones de los servicios de instalación de Windows, que serán instalados en el equipo destino si este no los posee o están desactualizados –esto puede forzar a reiniciar el sistema antes de continuar.

Es importante notar que la opción de comprimir la instalación debe estar deshabilitada si incluimos la BDE. Esto se nos avisa cuando configuramos el módulo.

Y esto es todo. Seleccionando la opción ‘Build’ del menú Build (o presionando F7) se compila todo en el formato seleccionado, y puede copiarse luego en el medio de instalación.

Page 20: Install Shield Express

Podemos también probar el instalador sin instalar nada, con la opción ‘Test your release’ que simulará todo el proceso de la instalación pero sin realizar realmente las acciones sobre el sistema.

La última opción nos permite copiar los archivos generados a cualquier ubicación, sin preocuparnos de cuáles son esos archivos. Muy conveniente para las compilaciones que no son de un solo archivo…

Y llegamos al final de nuestro paseo por InstallShield Express; espero que les sirva.

Pueden reportar cualquier error u omisión a [email protected]

Ernesto Cullen

Paraná, Entre Ríos, Argentina

19/02/2003