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

miércoles, 11 de noviembre de 2009

Hacer que un Textbox solo acepte numeros.

Bueno pues esto es algo que me han preguntado mucho, por ahi en la web he visto inclusive controles personalizados definidos para esta tarea, pero yo en particular prefiero las cosas sencillas y eficaces, asi que aqui les dejo un codigo de apenas unas lineas implementado en el evento KeyDown del textbox, que ocurre justo antes de que el caracter pulsado sea agregado en el textbox, esto es muy util si desarrollan aplicaciones con calculos, como una calculadora por ejemplo.

Ok y aqui esta el codigo


Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown


'Omitimos las teclas suprimir, flecha izquierda, flecha derecha, backspace, y el punto decimal
If e.KeyCode <> 190 And e.KeyCode <> Keys.Back And e.KeyCode <> Keys.Delete _
And e.KeyCode <> Keys.Right And e.KeyCode <> Keys.Left Then


'Verificamos que la tecla presionada este en el rango de 0 a 9, si no cancelamos
If e.KeyCode < Keys.D0 Or e.KeyCode > Keys.D9 Then
e.SuppressKeyPress = True
End If
End If


'Si se tecleo el punto decimal ,verificamos que el textbox no contenga ya un punto decimal
'Al mismo tiempo verificamos que el textbox no este vacio
If e.KeyCode = 190 And (TextBox1.Text.Contains(".") Or TextBox1.Text = "") Then
e.SuppressKeyPress = True
End If


End Sub

Cualquier error por favor haganmelo saber.


Probado en Visual Basic 2008

martes, 10 de noviembre de 2009

Obtener la captura de la pantalla en VB .Net sin API

Bueno pues aqui les dejo una funcion para obtener la captura de la pantalla utilizando objetos declarados con el namespace System.Drawing, simplemente mandamos a llamar la funcion y nos devolvera un objeto del tipo image, el cual podemos almacenar o asignar a un PictureBox


Private Function CaptureScreen() As Image
'Declaramos un rectangulo llamado limites
Dim Limites As Rectangle
'Decalaramos un mapa de bits para almacenar nuestro resultado
Dim Captura As System.Drawing.Bitmap
'Declaramos un grafico para obtener la captura
Dim graph As Graphics
'El rectangulo tiene el tamaño de nuestra pantalla
Limites = Screen.PrimaryScreen.Bounds
'Creamos el nuevo bitmap con el tamaño del rectangulo
Captura = New System.Drawing.Bitmap(Limites.Width, Limites.Height, _
System.Drawing.Imaging.PixelFormat.Format32bppArgb)
'Guardamos el resultado en el grafico
graph = Graphics.FromImage(Captura)
'Obtenemos la imagen dentro de nuestra pantalla a nuetro grafico
graph.CopyFromScreen(Limites.X, Limites.Y, 0, 0, Limites.Size, CopyPixelOperation.SourceCopy)
'Devolvemos la imagen
Return Captura
End Function

Despues de esto tan solo habria que llamar la funcion de la siguiente forma:

PictureBox1.image = CaptureScreen() 

Con esta funcion nos evitamos utilizar las APIs y lo hacemos mediante graficos, sencillo y eficaz

Probado en Visual Basic.Net  2008

lunes, 12 de octubre de 2009

Tutorial de programacion en 3 capas desde cero

Pues aqui les dejo un tutorial que hice, por su extension esta en PDF y pues es sobre el tema de la programacion en 3 capas , este tutorial esta pensado desde cero, para aquellos que han tenido contacto minimo o nulo con el tema, esta lo mas detallado que me fue posible.

Esta pensado para el enlace con bases de datos de SQL utilizando SQL server 2008 o 2005 y codificado paso por paso en visual studio 2008 utilizando visual basic, aunque es facilmente migrable a C#.

Espero les agrade, y pues ya saben cualquier detalle o sugerencia, por favor haganmelo saber.



DESCARGAR

viernes, 9 de octubre de 2009

Descargar un archivo via FTP

Pues aqui dejo una sencilla funcion para descargar un archivo mediante FTP, recive como parametros el nombre del archivo a descargar, el nombre que tendra despues de la descarga, el nombre de usuario ,el password de conexion, y la direccion del servidor, devuelve un booleano para saber que se completo la descarga.

----------------------CODIGO-------------------------------------

Private Function DescargaArchivo(ByVal Filename As String, ByVal NewFileName As String, _

ByVal UserNameFtp As String, ByVal PassFTP As String, ByVal URI As String) As Boolean


Dim Ftpconection As FtpWebRequest = CType(FtpWebRequest.Create(URI & "/" & Filename), FtpWebRequest)

' Creamos la nueva conexion del tipo web request donde URI es la direccion del servidor

Ftpconection.Credentials = New NetworkCredential(UserNameFtp, PassFTP)

'Asignamos las credenciales para el servidor

Ftpconection.Method = WebRequestMethods.Ftp.DownloadFile

'El metodo que utilizaremos como peticion, en este cado el de descargar

Try

Dim response As System.Net.FtpWebResponse = CType(Ftpconection.GetResponse, System.Net.FtpWebResponse)

Dim responseStr As IO.Stream = response.GetResponseStream

'guardamos el stream de datos

Dim fstr As New IO.FileStream(NewFileName, IO.FileMode.Create)

Dim buffer(2047) As Byte 'Buffer de transferencia

Dim ReadStream As Integer = 0

Do

ReadStream = responseStr.Read(buffer, 0, buffer.Length) 'leemos el stream de los datos

fstr.Write(buffer, 0, ReadStream) 'escribimos en el archivo

Loop Until ReadStream = 0

responseStr.Close() 'cerramos los archivos y las conexiones

fstr.Flush()

fstr.Close()

responseStr.Close()

response.Close()

Return True

Catch ex As Exception

Return False

End Try


End Function

----------------------CODIGO-------------------------------------

Este codigo requiere que agregemos la referencia

Imports System.Net

Ejemplo probado en Visual studio 2008