lunes, 24 de septiembre de 2012

Instalación de PostgreSQL en forma desatendida desde C#

  Hola:
  Este va a ser el primer post de una serie de post para PostgreSql con c#.
  En esta oportunidad me voy a centrar en la instalación desatendida y en algunos
inconvenientes que han surgido y que supe superar.
  En los sucesivos post, explicaré cómo conectar,crear una base de datos y tablas desde C#
con PostgreSQL, debido a que vi muy poco material sobre esto ya que la mayoría te enseña a
conectar PostgreSQL con C# y te dicen que hagas las tablas en pgAdmin o desde la línea de
comandos, esto estaría bien si fuese yo solamente quien va a usar la aplicación o si
nosotros vamos a instalarle al cliente el sistema, pero si queremos hacer una aplicación
para distribuir en masa, no le vamos a pedir a nuestro cliente que haga ese trabajo que debería
hacer nuestra aplicación sin la menor intervención de él, sería como que me vendieran un
auto nuevo y me pidan que yo me encargue de armar el motor.
  Me adelanto a que seguramente van a surgir muchos que ofrezcan mejores soluciones, serán
bienvenidas por supuesto, yo lo que voy a escribir es algo probado por mi, espero que
quienes sugieran otra cosa, den prueba de que lo de ellos ha funcionado.
  Cuando uno hace un instalador, puede empaquetar el .exe instalador del motor de la bd, y
ejecutarlo en el mismo instalador de la aplicación, siguiendo la misma línea de comando que
voy a usar para C#, será cuestión de gustos. A mi me gusta preguntar desde C# si será una
instalación que hará de Cliente o que hará de Servidor. La diferencia es que si es Cliente
no necesariamente hay que instalar PostgreSQL, solamente hay que instalar su conector.
  Algún que otro experto en instaladores podrá saltar y decir muchas cosas que darán por
hecho, pero yo prefiero ser experto en C# y no tanto en instaladores.


Detalles y discusiones previas:

  La versión de PostgreSQL que voy a usar es la 9.2 y se la puede descargar desde esta
dirección: http://www.enterprisedb.com/products-services-training/pgdownload#windows
Allí eligen la mas común que es la versión para Win x86-32, obvio que si tienen un Windows
de 64 bits, deben elegir la otra opción.
Esta versión posee un instalador distinto a la de la versión 8.3 que era un instalador msi
y cuyas opciones de instalación son otras a las que se presentan a partir de la versión
8.4. Les recomiendo que usen la misma versión que yo, porque si les surgen inconvenientes
al menos se descartará que sea por culpa de una versión diferente.
  Una vez descargado, pueden probar si quieren instalarla en forma normal para ir viendo las
opciones, este post sólo tiene el objetivo de instalar en forma desatendida.
En algunos windows de algunas máquinas (sobre todo en windows machacados, de esos que hay
que reinstalar urgentemente) al instalar en forma normal, tiraba algunos errores y no se
terminaba instalando PostgreSQL, estos errores eran con el instalador de EnterpriseDB, no
había dramas con los instaladores msi para la versión 8.3, quizás en esos windows
machacados faltaba algún archivo o algo pasaba que realmente desconozco, pero al instalar
en forma desatendida, se instalaba perfectamente.
  Usaré además el excelente IDE SharpDevelop 4.2.

Instalando desde la línea de comandos:
  Antes que nada les muestro como sería instalar desde la línea de comandos de windows.

A continuación les presento las opciones de instalación que existen en
PostgreSQL 9.2:

--help                         Display the list of valid options
--version                      Display product information
 --unattendedmodeui <unattendedmodeui> Unattended Mode UI
                                Default: minimal
                                Allowed: none minimal minimalWithDialogs
 --optionfile <optionfile>      Installation option file
                                Default: 
 --debuglevel <debuglevel>      Debug information level of verbosity
                                Default: 2
                                Allowed: 0 1 2 3 4
 --mode <mode>                  Installation mode
                                Default: qt
                                Allowed: qt win32 unattended
 --debugtrace <debugtrace>      Debug filename
                                Default: 
 --installer-language <installer-language> Language selection
                                Default: en
                                Allowed: en es fr
 --extract-only <extract-only>  
                                Default: 0
 --superaccount <superaccount>  Sets the user name of the database superuser. Defaults to 
'postgres'.
                                Default: postgres
 --servicename <servicename>    Sets the name of the database service.
                                Default: 
 --serviceaccount <serviceaccount> Sets the operating system user account that owns the 
server process. Defaults to 'postgres'.
                                Default: 
 --servicepassword <servicepassword> Sets the password for the operating system user 
account that owns server process. Defaults to superuser password.
                                Default: 
 --install_runtimes <install_runtimes> Specifies whether or not install the Microsoft 
Visual C++ runtimes before the installation proceeds.
                                Default: 1
 --create_shortcuts <create_shortcuts> Specifies whether or not menu shortcuts should be 
created.
                                Default: 1
 --prefix <prefix>              Installation Directory
                                Default: C:\Archivos de programa\PostgreSQL\9.2
 --datadir <datadir>            Data Directory
                                Default: C:\Archivos de programa\PostgreSQL\9.2\data
 --superpassword <superpassword> Password
                                Default: 
 --serverport <serverport>      Port
                                Default: 5432
 --locale <locale>              Locale
                                Default: 

  Desde la linea de comandos se instalaría de la siguiente manera suponiendo que al archivo
instalador le dejé el mismo nombre con el que se descarga y el mismo se encuentra en el directorio raíz de windows:
C:\>postgresql-9.2.0-1-windows.exe --mode unattended --superpassword mipass  
--servicepassword mipass --serverport 5434 --unattendedmodeui none  --prefix 
C:\PostgreSQL\9.2 --datadir C:\PostgreSQL\9.2\Data
     
--mode unattended: Significa que será en modo desatendido.
--prefix C:\PostgreSQL\9.2: Significa que voy a instalar la base de datos en el directorio
C:\PostgreSQL\9.2, es decir que cambio el que viene por defecto  que es C:\Archivos de
programa\PostgreSQL\9.2\data.
--datadir C:\PostgreSQL\9.2\Data: Instalo los datos en el directorio C:\PostgreSQL\9.2\data en
lugar del que viene por defecto que es C:\Archivos de programa\PostgreSQL\9.2\data.
--serverport 5434: Uso el puerto 5434 y no el que viene por defecto que es el 5432 (si quieren dejen el por defecto que es l que se usa mas comunmente).
--unattendedmodeui none: Le digo que no muestre ni siquiera la ventana mínima.
--superpassword mipass: Establece el password que en este caso será "mipass". Si no colocan esto el pass por defecto será "postgres".

  También puede colocarse otras opciones como --install_runtimes en donde colocando 0 se le
dice que no instale los runtime  visual c++ que necesita para funcionar, pero lo conveniente es
dejar lo que viene por default, osea 1, por si la máquina en que se va a instalar no lo
posee.


Instalando desde C#:
  Primero creo una clase, esta clase se va a llamar InstalacionPostgreSQL y va a tener dos métodos, uno que se va a llamar "Instalar" y va a devolver un bool y el otro se va a llamar "ComprobarSiExiste" que va a devolver un booleano que si es true significa que existe, sino, no existe, este método lo que hace es buscar la clave del registro de PostgreSQL.
  El ejecutable de la instalación de PostgreSQL en esta oportunidad va a estar dentro de la carpeta Installers que vamos a tener dentro de la carpeta donde se encuentra el ejecutable de nuestra aplicación en C#.
  Es recomendable colocar una barra de progreso en una ventanita cosa de mostrarle al cliente que se está instalando algo, debido a que tarda un poco y el cliente puede pensar que la máquina se tildó o algo por el estilo.
 A continuación la clase instaladora:

//Dos espacios de nombres que se van a usar, uno sirve para ejecutar procesos y el otro
//para leer claves en el registro
using System.Diagnostics;
using Microsoft.Win32;

public class InstalacionPostgreSQL  //Nombre de la clase
 {
public InstalacionPostgreSQL() //Constructor sin parámetros
{}
public bool Instalar()  //Función que instala PostgreSQL
{
//Paso al string la ruta del ejecutable de nuestra aplicación
string ruta=Application.StartupPath;
//Le paso que el directorio por defecto sea el del ejecutable
Directory.SetCurrentDirectory(ruta);

//En los siguientes strings indico los parámetros y qué archivo se ejecuta
string installerpostgre=@"--mode unattended --superpassword mypass  --servicepassword mypass --serverport 5434 --unattendedmodeui none  --prefix C:\PostgreSQL\9.2 --datadir C:\PostgreSQL\9.2\Data";
string x="Installers\\postgresql-9.2.0-1-windows.exe";

Process oProc = new Process();//Creo el proceso
try //Con este try catch atrapo cualquier excepción que se produzca
{
oProc.StartInfo.RedirectStandardInput = true;
oProc.StartInfo.RedirectStandardOutput = true;
oProc.StartInfo.CreateNoWindow=true;//Le indico que no debe abrir la típica ventana DOS cuando           ejecuto el proceso
oProc.StartInfo.UseShellExecute = false;
oProc.StartInfo.FileName = x;//Le indico que debe ejecutar el archivo del path que se encuentra en este string
oProc.StartInfo.Arguments = installerpostgre;//Le paso los parámetros que contiene este string
oProc.Start();//Comenzar el proceso
oProc.WaitForExit();//Esperar a que termine el proceso para terminar
oProc.Close();//Cierro el proceso
}
catch{
return false;//Si hubo error, retorno false 
}

MessageBox.Show("Se ha instalado PostgreSQL 9.2.");//Aviso que se instaló correctamente

return true;//Retorno true para que se sepa que se instaló correctamente
}

bool   ComprobarSiExiste()
{
string clavreg=@"SOFTWARE\PostgreSQL\Installations\postgresql-9.2";
 // Abrimos la clave del registro con la que queremos trabajar
RegistryKey rk1 = Registry.LocalMachine;
// Nos movemos hasta la subclave donde queremos trabajar.
// El parámetro boleano indica si la abrimos en solo lectura (false)
// ó en lectura/escritura (true).
rk1 = rk1.OpenSubKey(@clavreg,true);
// Si devuelve null es que la clave no existe
if (rk1 == null)
   return  false; //No existe entonces retorno falso
else
return  true;//Existe entonces retorno verdadero
}

}//Fin de la clase


                       Errores con los que me topé:

  Asegúrensen de tener el editor del código de SharpDevelop en fuente tipo Unicode como puede ser Arial Unicode MS porque puede mal interpretar los dos guiones seguidos "--" y a uno interpretarlo como otro carácter, es por eso que si le aparece un cartelito que les indica en inglés que se fije en la ayuda del instalador, prueben cambiar la fuente del editor yendo a Herramientas-Opciones-Editor de Texto de SharpDevelop y allí cambiar dicha fuente. Ahora lo cuento como algo sencillo pero estuve bastante para saber que era eso tan simple.
  Investigando en instalaciones de PostgreSQL 9.2 me he topado con que muchos en lugar de
colocar --serverport, colocan --port o mas adelante cuando se vea creación de base de datos PostgreSQL 9.2 y creación de tablas, para realizar la conexión colocan --server en lugar de --host, esto tiene como resultado que no se instala PostgreSQL 9.2 ni se crea ni la base de datos y por supuesto, tampoco las tablas. Ojo! en la "Conexión" a PostgreSQL 9.2 una vez instalada ésta, sí hay que usar --port en vez de --serverport, ignoro por qué lo hicieron así, pero en la "Instalación Desatendida" es al revés. Otro es que en lugar de --superpassword vi post que colocan --user o --user id, esto tampoco sirve, no se instala y en el caso de la creación de base de datos y tablas, tampoco sirve, porque ahora se usa --username.


                              Ejemplo de Aplicación:

  Supongamos que ya tenemos los formularios o una ventana WPF de una Agenda que va a Funcionar con PostgreSQL (Es un desperdicio usar PosgreSQL para una agenda, convendría usar algo como SQLite, pero aquí es a modo de ejemplo).
  Usando la clase InstalacionPostgreSQL podríamos hacer algo así:

public partial class Agenda : Window
{
#region {Globals Variables}
InstalacionPostgreSQL InPostgre=new  InstalacionPostgreSQL ();  //Creo un objeto de la clase
#endregion {Globals Variables}

#region {Constructor}
public Agenda()
{
InitializeComponent();//Cargo los componentes de la agenda, que puede ser una Datagrid o cualquier //elemento que uno haya colocado en el WPF

if(!InPostgre.ComprobarSiExiste()) //Pregunto si no existe PotgreSQL
{
//Si no existe instalo
InPostgre.Instalar();

}
}
#endegion {Constructor}
 }//Fin clase





9 comentarios:

  1. Me funciona perfectamente, muchas gracias, pero como puedo hacer para que no se instale tambien el pgadmin3?

    ResponderEliminar
  2. Hola:
    En las aplicaciones que tuve que hacer me han pedido tener el pgadmin, por eso no me puse a ver como quitarlo, pero lo que supongo que mas te interesa es que no aparezca en el menú de windows su existencia, es decir que para que esto ocurra hay que colocar --create_shortcuts 0 junto a las demás opciones ya que por defecto viene 1 (crea el menú) y colocando 0 lo que hace es no crear en el menú de windows el directorio de postgre con los accesos directos de pgadmin. Tengo que probarlo todavía, ando con poco tiempo, pero en esta semana seguro pruebo a ver si funciona. Igualmente busqué así nomás a ver si había alguna opción para no instalar específicamente el pgadmin como sí existe para instalar o no el pl/pgsql y se coloca --install_plpgsql 0, esto es según la siguiente página: http://www.arpug.com.ar/trac/wiki/OneClickInstaller
    Es raro ya que este comando no aparece en la lista válida de opciones de instalación y lo más probable es que no funcione.
    Si funcionara lo anterior, entonces, en teoría debería haber algo como --install_pgadmin 0 para no instalar el pgadmin, pero no he encontrado si existe un comando así todavía. Saludos.

    ResponderEliminar
  3. excelente aporte me salvaste la vida

    ResponderEliminar
  4. Me marca un error en Aplication

    ResponderEliminar
    Respuestas
    1. En qué momento? probaste en otro sistema? dá mas detalles.

      Eliminar
  5. Hola,
    Tengo problemas al comprobar si existe, la llave siempre es null, por lo que siempre intenta hacer la instalacion

    ResponderEliminar
    Respuestas
    1. Hola, le debés estar errando con la clave del registro
      @"SOFTWARE\PostgreSQL\Installations\postgresql-9.2";
      esa es si instalaste la versión 9.2, si instalaste otra versión por ejemplo la 9.1 sería así la clave
      @"SOFTWARE\PostgreSQL\Installations\postgresql-9.1";
      verificá en el registro la clave correcta.

      Eliminar
  6. Echa un vistazo a una herramienta gratuita - Valentina Studio. Producto asombroso! OMI es el mejor gestor de PostgreSQ, para todas las plataformas. http://www.valentina-db.com/en/valentina-studio-overview

    ResponderEliminar

Escriba su comentario...