miércoles, 5 de mayo de 2010

Detectar el cierre de una aplicacion con VB.Net

Bueno pues esto es algo que tal vez tiene muchas posibles soluciones, aun asi decidi publicar la mia.

Generalmente para hacer esto he visto que se hace con un timer para monitorear mediante la clase process cada determinado tiempo los procesos existentes, buscar el proceso para saber si aun se esta ejecutando, esto es funcional y valido, aunque me vino la idea de generar un evento que se desencadene en el momento justo en que el proceso termina, asi que se me ocurrio esta solucion:

En mi interfaz grafica solo tengo un form (Form1) con un Boton y un textbox (Button1,TextBox1) .


Imports System.Threading

Public Class Form1

'Declaro mi evento reciviendo como parametro el nombre del proceso
Private Event ProcessClosed(ByVal ProcName As String)

'Creo mi metodo que permanecera en un thread esperando
'a que el proceso cierre, reciviendo como parametro el
'nombre del proceso como objeto
Public Sub VerifyProcess(ByVal ProcName As Object)
'Declaro la matriz de procesos
Dim proc() As Process
'Lleno la matriz con los procesos que contengan el nombre
'dado como parametro
proc = Process.GetProcessesByName(CStr(ProcName))
'Verificamos que existan procesos con ese nombre
If  proc.Length <> 0 Then
'Esperamos a que el proceso termine, solo hice referencia
'a la primera ocurrencia del proceso, pero solo bastaria crear
'un nuevo thread para cada proceso con el mismo nombre con ayuda de
'un ciclo
proc(0).WaitForExit()
'una ves terminado desencadenamos el evento
RaiseEvent ProcessClosed(CStr(ProcName))
Else
'No se encontro el proceso
MessageBox.Show("No existe el proceso "CStr(ProcName))
End If

End Sub

Private Sub Procces_Closed(ByVal ProcName As String) Handles Me.ProcessClosed
'Aqui la accion cuando se desencadeno el evento
MessageBox.Show("Se ha cerrado el proceso " &  ProcName)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Aqui agregamos el thread al threadpool, asi nuestra aplicacion no se pasma
ThreadPool.QueueUserWorkItem(AddressOf VerifyProcess, TextBox1.Text)
End Sub

End Class

Asi podemos crear varios threads para verificar varios procesos a la vez, simplemente basta con escribir el nombre de un proceso, por ejemplo "notepad" o "firefox" en el textbox, y despues de presionar el boton se habra agregado el thread y al cerrar dicha aplicacion nos saldra un mensaje de que el proceso ha sido cerrado.

Como siempre en probado en VB.2008

jueves, 21 de enero de 2010

Validar que una direccion de Email tenga la estructura correcta

Bueno en un comentario que recivi, me sugirieron que publicara un codigo para validar un correo,  supongo que se refiere a una dirrecion de Email, asi que aqui les dejo la propuesta.

En este ejemplo solo haremos uso de un boton y un textbox.

Esta es una simple funcion que ejemplifica mediante la manipulacion de cadenas como validar una direccion de correo, en si esto seria la base para un analizador sintactico ( muy basica ), y consiste en analizar la estructura de una cadena para que se ajuste a ciertas reglas, esta sencilla funcion puede mejorarse asi que acepto sugerencias.


Private Function ValidaEMail(ByVal EMail As String) As Boolean

'Como primera regla un correo electronico debe contener la @
If Not EMail.Contains("@") Then
Return False
End If

'Dividimos la cadena en secciones, obviamente estas deben ser 2
'el usuario y el host, utilizamos como separador la @
Dim SeccionesEMail As String() = EMail.Split(CChar("@"))

'Ahora verificamos que evidentemente solo sean 2 secciones, ya que
'en caso contrario eso significa que hay mas de una @ y eso es incorrecto
If SeccionesEMail.Length <> 2 Then
Return False
End If

'Ahora verificamos que la segunda seccion de la cadena de correo contenga
'al menos un punto, ya que la seccion del dominio debe contener el punto
'Podemos establecer un tamaño minimo para el dominio en este caso le puse 3
If Not SeccionesEMail(1).Contains(".") Or Not SeccionesEMail(1).Length >= 3 Then
Return False
End If

Return True

End Function

En esta funcion aun necesitan corregirse detalles , ya que por ejemplo validaria la direccion "MyCorreo@...", la cual no es valida, pero pues eso ya es cuestion de continuar manipulando la cadena y estableciendo mas reglas.
Despues solo llamamos la funcion asi:


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'Aqui hacemos la llamada a nuestra funcion
If ValidaEMail(TextBox1.Text) Then
MessageBox.Show("Correo valido")
Else
MessageBox.Show("Correo invalido")
End If

End Sub

Bueno esta seria la forma rudimentaria de hacerlo, pero a mi me gustan las cosas sencillas, y sabemos que el Framework nos provee de muchas herramientas para hacernos todo mas facil asi que, si lo queremos hacer todavia mas sencillo simplemente utilizamos la clase MailAddress, que esta en System.Net.Mail, creamos una instancia y esta nos evaluara de forma automatica si el formato es correcto.


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Try
'Creamos nuestro objeto, el constructor recive la cadena como parametro
Dim mail As New System.Net.Mail.MailAddress(TextBox1.Text)
'Al crear nuestro objeto evalua la cadena, y si es correcta no se produce
'ningun error
MessageBox.Show("Correo valido")
Catch ex As Exception
'En caso de que el formato de la cadena sea incorrecto nos produce una exepcion
'del tipo FormatException, ni necesidad tenemos que escribir el mensaje de error
'simplemente lo obtenemos de la exepcion
MessageBox.Show(ex.Message)
End Try

End Sub

Y asi podemos validar una direccion de correo, sencillo y eficiente ,  ¡suerte! , cualquier sugerencia o comentario son aceptados.


Probado en VS.net 2008



 

martes, 19 de enero de 2010

Cargar un ensamblado DLL o Exe durante el tiempo de ejecucion

Bueno, pues ya tenia un poco descuidado mi blog, con el trabajo es dificil darse el espacio para continuar colocando entradas, pero tratare de ser mas constante, ok.

Y volviendo al tema, para empezar, la idea de esto comenzo con la inquietud de crear una aplicacion basada en plugins, que en el momento de su ejecucion verificara las Dlls existentes que contienen controles personalizados, y agregara dichos controles al formulario principal, esto me tomo un tiempo, ya que me involucre con situaciones de realizar llamadas a API, Hooks, e inclusive algunos manualillos que hay por ahi en la web que hablan de la inyeccion Dll, admito que estuve a punto de darme por vencido, pero como siempre, y despues de dormir un poco, ya mas despejado, y despues de leerme un curso sobre ensamblados y dominios de aplicacion, me sorprendio lo facil que es lograr esto, asi que aqui les va la solucion que encontre.

Resulta que mi aplicacion principal le coloque un control TabControl, para agrupar mis plugins (Mis dlls) en TabPages, asi que la intencion es crear un nuevo tabpage por cada Dll que este en el mismo directorio de mi aplicacion, y agregar el control que contiene.

Para esto haremos uso de la clase assembly que esta contenida en System.Reflection, esta clase nos permite instanciar un ensamblado el cual puede ser un Dll o un Exe, asi que aqui esta el metodo que cree explicado:


Public Sub AddAssembly(ByVal Path As String)

'Declaro mi objeto del tipo Assembly, y cargo el fichero
'El cual es el path donde se ubica mi dll
Dim MyAssembly As Assembly = Assembly.LoadFile(Path)

'Como el nombre de mi control, mi ensamblado y mi clase son iguales
'la referencia para un control instanciado de la clase MyControl seria
'MyControl.MyControl asi que aqui simplemente extraigo el nombre de mi
'archivo sin la extension, se vera algo rudimentario pero funciona :)
Dim sClase As String = MyAssembly.ManifestModule.Name.Split(CChar("."))(0)

'Aqui obtengo el tipo de dato que tengo en mi Dll
Dim MyExtType As Type = MyAssembly.GetType(sClase & "." & sClase)

'Entonces creo la instancia nueva de acuerdo al tipo de dato obtenido
'la almaceno en mi objeto tipo object
Dim MyExtObj As Object = Activator.CreateInstance(MyExtType)

'Creo mi tabPage
Dim NewTabPage As New TabPage

'Aqui convierto mi objeto a control, probablemente esto deberia ir en
'un try catch para obtener alguna exepcion, por ejemplo que la DLL no contenga
'controles
Dim MyControl As Control = CType(MyExtObj, Control)

'Agrego el nuevo control creado
NewTabPage.Controls.Add(MyControl)

'Agrego el nuevo TabPage a mi TabControl
form.TabControl1.TabPages.Add(NewTabPage)

End Sub



Asi solo mandamos a llamar a dicho metodo y como parametro utilizamos el path de la Dll, instancia el control y lo agrega a nuestro formulario principal.


Facil ¿no?, espero le ahorre un dolor de cabeza a alguien.

Probado en VS .Net 2008