sábado, 12 de septiembre de 2009

[Winform] Realizar tareas antes de inicializar aplicación

 

Introducción


Algunas veces en las aplicaciones es necesarios desplegar una ventana de login, o un formulario de inicio, o ambos, esto genera un gran problema cuando la aplicación esta iniciada, ya que la ventana principal del formulario se encuentra visible. La idea es poder realizar operaciones previas a la visualización de la pantalla definida como principal.

Es por ello que existe un área (o método) previa al inicio, en donde se puede realizar operaciones previas al inicio de la aplicación.

Esta función tiene el nombre de Main()

 

C# – Main


Cuando se crea una “Windows Applicacion”, se podrá apreciar una clase de nombre: Program.cs

Esta clase es clave para poder realizar trabajos previos.

De forma inicial encontrara código similar al siguiente:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

Las aplicaciones Windows en C#, siempre inician en un método Main.

Por supuesto podrá acomodarse para que realice algunas tareas previas, como ser, el mostrar un cuadro de login:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    //
    // Realizo la apertura del formulario para validar el login
    // esta tarea es previa al inicio de la aplicacion
    //
    frmLogin login = new frmLogin();
    login.ShowDialog();

    //
    // Si el login es correcto, procedo con la apetura normal
    // de la aplicacion
    //
    if (login.DialogResult == DialogResult.OK)
        Application.Run(new frmPrincipal());

}

Como se observa en el código en las líneas 11 y 12, se incia un nuevo formulario, que tendrá la responsabilidad de de la autenticación de usuario.

Dependiendo del resultado de la operación previa es que se dará inicio, o no, al hilo principal de la aplicación.

Algunos puntos interesantes a destacar:

  • Es necesario que los formulario previos realicen una pausa en la ejecución de método Main(), es por eso que se hace uso del ShowDialog() para mostrar el formulario de login. En este caso el simple Show() no podrá ser utilizado ya que este no produce un stop, sino que deja al método Main() continuar su ejecución
  • El código de las líneas 4 y 5 siempre serán las primeras líneas del método  Main(), ya que estas deben ejecutarse previas al despliegue de cualquier formulario
  • Como se observara en ningún momento se hizo uso de alguna funcionalidad de exit, o quit que cerrara la aplicación, simplemente con evitar pasara por la asignación de un formulario en Application.Run(), fue suficiente.

 

VB.NET – Sub Main


Si bien la explicación de este método en C# es bastante similar a la de VB.NET, deben remarcarse algunas diferencias que son fundamentales para lleva a cabo la tarea de forma correcta.

En principio al crear la Windows Application en VB.NET, esta no creara el archivo de clase “Program”, o similar, como si se hace en C# de forma automática. Es por eso que la creación de la clase deberá hacerse de forma manual.

En el ejemplo se visualizará una clase de nombre “SubMain.vb”, y dentro de esta el siguiente código:

<STAThread()> _
Shared Sub Main()

    Application.EnableVisualStyles()
    Application.SetCompatibleTextRenderingDefault(False)

    Dim login As frmLogin = New frmLogin
    login.ShowDialog()

    If (login.DialogResult = DialogResult.OK) Then

        Application.Run(New frmPrincipal)

    End If

End Sub

Como verán es prácticamente idéntico método Main() codificado en C#.

Bien hasta aquí todo perfecto, pero falta un paso mas que tal vez no sea tan obvio como parece.

Resulta que para que la aplicación VB.NET pueda tomar el método Main() como inicio hay que desmarcar la el check de nombre “Enable Application framework”

VB.NET SubMain Startup

Como se observa en la imagen, este check esta desmarcado y es en ese momento en donde se puede cambiar en el combo “Startup object” al método Sub Main.

En este link: Cómo: Cambiar el objeto inicial de una aplicación (Visual Basic)

Se encontrará una explicación mas amplia del tema.

 

Conclusión


Haciendo uso de método Main() se puede realizar operaciones previas a la carga del formulario principal de la aplicación de una forma simple y prolija.

 

[C#] 
[VB.NET] 

28 comentarios:

  1. Excelente el tutorial ha sido de mucha utilidad se agradece su publicacion! :):):):):):)

    ResponderEliminar
  2. Hola Leandro... te hago una consulta... por que cuando quiero bajar los ejemplos y quiero descomprimir los archivos zipeados me tira error como que el archivo esta dañado ?

    ResponderEliminar
  3. hola

    La verdad es raro esto que comentas con los .zip, realice la prueba descargando los archivos desde el propio blog para validar si hay algun error

    Pero no he tenido ningun problema en la descompresion

    Una consulta estas usando Visual Studio 2008 ?

    En el articulo no lo aclare pero estos ejemplos estan creando con esta version de IDE de VS, podria se un problema si es que quiere abrir la solucion

    saludos

    ResponderEliminar
  4. Hola LinuxMan yo descargo y abro sin ningún problema.

    Saludos.

    ResponderEliminar
  5. LinuxMan tu problema es el siguiente.. cuando bajas el zip, se te baja directamente a la carpeta download o descargas, una vez que abras el zip copia esa carpeta con el proyecto a alguna carpeta vacia por ej. C:Proyectos y ahí abrí el proyecto. De esa forma te deberia funcionar sino ya es problema del compilador que no debe ser la version adecuada

    ResponderEliminar
  6. no mames para los que estamos migrando o iniciando en estos nuevos lenguajes es una cagada, ahora resulta que para mostrar un form no basta con el .show y para cerrar con el unload... en vez de que vaya siendo mas simple.

    Excelente ejemplo ya lo baje de peluche.

    ResponderEliminar
  7. Muy bueno el tutorial. Felicitaciones.
    Aprovecho para preguntar:
    Si desde la ventana de login manejo la validación del usuario que quiere entrar a la aplicación, ¿Cómo puedo mantener o pasar los datos de la identidad del usuario que se validó para poder acceder a ellos desde la siguiente ventana del formulario principal, una vez que la ventana de logín se cierra y se activa el método application.run(frm_principal)?

    ResponderEliminar
  8. hola Jose

    lo ams simple podria ser ponerlo de forma global para que accedan los demas formulario

    [Winforms] Singleton - Pasar datos entre formularios

    con un singleton pdorias lograrlo y de paso que quede prolijo

    saludos

    ResponderEliminar
  9. hola.me párese muy interesante tu entrada, me gustaría que me ayudaras un poco mas ya que en base a los usuarios registrados quiero otorgarles privilegios d modificación o inserción de datos. mi sistema es para un hospital para el manejo de expediente electrónico clínico y mis usuarios serian los médicos..

    ResponderEliminar
  10. hola Erika A.B

    esta un poco incompleto el planteo

    comentas que quieres darle privilegios al usuario pero no mencionas como defines esta info, o si es funcionalidad que aplciara visualmente a un control o es algo asm de negocio

    igualmente creo que plantear algo como esto podria ser extendo, quizas sea algo mas para un foro

    foro c#

    saludos

    ResponderEliminar
  11. hola leandro quiciera q me ayudaras con algo soy nuevo en esto de la programacion tengo una duda como hago para modificar los datos de una clase mediante windforms tengo un panel en el cual creo el objeto con los taributos entonces cuando se guarde me muestre alli mismo en ese panel en una lista el id del objeto creado y q si lo quiero modificar lo selecciono de la lista me vuelva a cargar los datos de este mismo en lo campos donde los creo para modificarlos y luego guardarlos nuevamente con los datos ya modificados

    ResponderEliminar
  12. hola beymer

    apuntas a algo como esto

    [WinForms] Edición Empleados

    en ese articulo se utilizan clases para definir las entidades y se editan para actualizarlas en la tabla

    saludos

    ResponderEliminar
  13. Hola, estoy desarrollando una aplicación con una arquitectura semenjante a la que planteas, el problema o duda que tengo es:

    Debuggeando la aplicación, una vez instanciado el Form principal, el Form que juega el papel de login se queda en memoria, si reviso la variable y sus propiedades ahi estan cada uno de ellos.

    He probado con los metodos Close(), Dispose() pero no logro quitarla de memoria.

    He codificado muchas versiones tratando de hacer mi aplicación mas ligera al ejecutarse pero hasta ahora no he podido.

    ¿Tu sabes alguna forma de destruir ese objeto una vez que ha servido para instanciar al otro?.

    Saludos.

    ResponderEliminar
  14. hola cayen

    pero estas implementando el login en el Main() ?
    porque si es asi y alli creas la instancia del form de login, al cerrar el form esta se destruye, no veo como puedes tener visibilidad desde otro punto de la aplicacion para validar que aun esta en memoria

    saludos

    ResponderEliminar
  15. Hola Leandro.

    Así es, dentro del Main() instancio un nuevo Login y si el DialogResult==DialogResult.OK entonces abro mi form principal.

    Lo he tratado de hacer de varias formas:

    1)
    vLogin LOGIN = new vLogin();
    LOGIN.ShowDialog();

    if (LOGIN.DialogResult == DialogResult.OK)
    {
    Application.Run(new vMenu(LOGIN.resultadoValidacion));
    LOGIN.Dispose();
    }

    2) En la anterior llegue a pensar que el LOGIN no podia destruirse hasta que termina el thread de Application asi que lo hice antes:

    vLogin LOGIN = new vLogin();
    LOGIN.ShowDialog();
    String[] R;

    if (LOGIN.DialogResult == DialogResult.OK)
    {
    R = LOGIN.resultadoValidacion;
    LOGIN.Dispose();
    Application.Run(new vMenu(R));
    }

    Le agrego puntos de interrupción en las lineas donde hago el Dispose() de LOGIN y al correr mi aplicación principal como tal, y en el debuggeador al buscar la variable 'LOGIN' aparecen las propiedades.

    No se que tan correcto sea hacer un 'LOGIN=null;'

    Ayer lo puse en lugar de la linea 'LOGIN.Dispose();' y al querer buscar la variable, aunque existe ya no hay datos.

    ¿Que me recomiendas hacer?. Habia pensado en hacer una aplicación MDI y/o un form principal con paneles que dentro de si mismo se carguen dependiendo de los resultados del LOGIN.

    Saludos y gracias por contestar.

    ResponderEliminar
  16. hola cayen

    la verdad no estoy seguro de lo que quieres lograr, ya que si asignas null o usas el Disponse(9 es seguro que al acceder a la variable de la instancia del form no puedas recuperar sus datos

    podria ser algo como

    DialogResult result = null;
    String[] R;
    using(vLogin LOGIN = new vLogin())
    {
    result = LOGIN.ShowDialog();
    if (result == DialogResult.OK)
    R = LOGIN.resultadoValidacion
    }

    if (result == DialogResult.OK)
    {
    Application.Run(new vMenu(R));
    }

    el using asegura la correcta destruccion del objeto

    saludos

    ResponderEliminar
  17. He querido implementar un login y me gustó la forma en que lo expones aqui, pero tengo un problema y me gustaria su ayuda. Si los datos que tipea el el usuario son incorrectos ¿Cómo hago para que no se ejecute el formulario principal y permanesca el formulario de login y permita al usuario realizar otro intento?

    ResponderEliminar
  18. Leando muhisimas gracias me fue de bastante utilidad

    ResponderEliminar
  19. Hola leandro, porque declaras a la clase como Friend y no como Public??
    La clase que contiene al sub main hablo.. gracias

    ResponderEliminar
  20. hola Si Señor

    por nada en particular
    podria ser public sin problemas, pero por lo general si esta no requiere ser utilizada por fuera de la libreria


    Access Levels in Visual Basic

    si sabes que una funcionalidad no debes ser utilizada por fuera de la dll donde se compila la defines de esa forma

    saludos

    ResponderEliminar
  21. Me funciono perfecto, pero antes de la login tenia una presentacion como puedo activarla o llamarla

    ResponderEliminar
  22. hola Dx

    podrias poner en el mismo Main() primero el form de inicio abriendolo con el ShowDialog() y luego cuando cierre abres el form de login y cuando termine asignas el Application.Run()

    puedes en el Main() ir llamando un form y luego otro, pero recuerda usar el ShowDialog()

    saludos

    ResponderEliminar
  23. Hola Leandro.
    Como debo trabajar al iniciar mi login, osea como almaceno temporalmente mi usuario y datos de ello en toda mi sesion en mi aplicacion Winform (Variables Globales).

    Muchas Gracias.

    ResponderEliminar
  24. hola Luis

    podrias aplicar una tecnica como est

    [Winforms] Singleton - Pasar datos entre formularios

    para conservar los datos del usuario de forma global para toda la aplicacion

    saludos

    ResponderEliminar
  25. Buenos dias, hay una manera de hacer esto en SharpDevelop?

    ResponderEliminar