Buscar este blog

viernes, 14 de junio de 2013

Registro de errores y eventos con NLog

Es muy importante llevar un registro de eventos y errores en nuestras aplicaciones de .Net, de esta manera podemos encontrar y resolver problemas inesperados, en particular es muy útil en Asp.Net donde podemos configurar los reportes para enviar los errores por correo y percatarnos de problemas en tiempo real.
En el sitio de NLog podemos descargar el instalador o las dlls de forma gratuita ya que el proyecto es open source, para la aplicación no es necesario usar el instalador solo hace falta incluir la dll en la carpeta de los binarios.

Para desarrollar lo mas practico es usar el instalador ya que el mismo provee integración con visual studio, en nuestro proyecto elegimos añadir un nuevo archivo y escogemos un archivo de configuración de NLog, esto añadirá las referencias adecuadas y un archivo de ejemplo de configuracion de NLog.



Después en las clases en las que queremos llevar un registro creamos un objeto estático de la clase Logger, la integración con Visual Studio incluye unos snipets, por que solo escribimos nlog presionamos tab dos veces y crea el código en automático:


private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();


Ahora para mandar un mensaje cualquiera tenemos varias funciones según el nivel de importancia con que queramos que aparezca el mensaje:


logger.Info("Hola");

Este mensaje tiene un nivel de importancia solo informacional.
Una característica de NLog es que podemos mandar como parte del mensaje un excepción y según nuestra configuración el mensaje puede tener un nivel de información muy detallado incluyendo el momento, el stakctrace y cuanta información requiramos de la excepción:

logger.FatalException("Error:", exception);


Suficiente como introducción más adelante hablaremos de la configuración de NLog.

jueves, 13 de junio de 2013

Obteniendo el tiempo desde la ultima actividad del usuario en Windows

El API de Windows nos proporciona una función para determinar el tiempo desde la ultima actividad del usuario: GetLastInputInfo.
Para usarla en .Net es necesario importarla desde la dll nativa user32.dll:



[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO {
    public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
 
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 cbSize;
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 dwTime;
}
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

La función importada puede ser usada para obtener por ejemplo el total de minutos que ha estado inactiva la sesión, solo funciona para sesión en que fue llamada la función:


private double GetLastInputTime() {
    uint idleTime = 0;
    LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
    lastInputInfo.dwTime = 0;
    uint envTicks = (uint)Environment.TickCount;
    if(GetLastInputInfo(ref lastInputInfo)) {
        uint lastInputTick = lastInputInfo.dwTime;
        idleTime = envTicks - lastInputTick;
    }
    TimeSpan span = new TimeSpan(0, 0, 0, 0, (int)idleTime);
    return span.TotalMinutes;
}

Hasta la próxima!

martes, 11 de junio de 2013

Cambiar de tamaño automaticamente la imagen de un Gtk.Image

A continuación les pongo el código de una clase que cambia estomáticamente el tamaño de un Gtk.Image al crear o cambiar el tamaño del objeto, es decir el equivalente a la propiedad zoom de un PictureBox de Windows.Forms.
El proceso es captar el evento expose que ocurre al cambiar de tamaño del objeto y ahí escalar la imagen usando la clase Gdk.Pixbuf para mantener la proporción de la imagen se crea el objeto dentro de un AspectFrame.

El código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gtk;
using Gdk;
 
namespace Test {
    internal class ImageResize {
        private Gtk.Image _Wrapped = null;
        private Pixbuf original = null;
        private string _File = null;
        public ImageResize(Gtk.Image wrapped) {
            _Wrapped = wrapped;
            _Wrapped.ExposeEvent += new ExposeEventHandler(ImageResize_ExposeEvent);
        }
        void ImageResize_ExposeEvent(object o, ExposeEventArgs args) {
            Pixbuf newPix = new Pixbuf(original.Colorspace, original.HasAlpha, original.BitsPerSample, _Wrapped.Allocation.Width, _Wrapped.Allocation.Height);
            double zoom = (double)((double)_Wrapped.Allocation.Width / (double)((double)original.Width));
            original.Scale(newPix, 0, 0, _Wrapped.Allocation.Width, _Wrapped.Allocation.Height, 0, 0, zoom, zoom, InterpType.Nearest);
            _Wrapped.Pixbuf = newPix;
        }
        public string File {
            get {
                return _File;
            }
            set {
                _File = value;
                original = new Pixbuf(_File);
                ImageResize_ExposeEvent(this, null);
            }
        }
    }
}

sábado, 8 de junio de 2013

Creación de eventos en c#

En c# hay varias formas de declarar un evento cada una de diferente complejidad según lo que queramos hacer, lo forma mas simple es marcar el miembro con la palabra clave event y de tipo que sea una de las múltiples clases que hay para manejar eventos puede ser interconstruida o propia de la aplicación.
Como vemos en el siguiente ejemplo también debemos declarar las clases para los argumentos si queremos pasar un valor especial al evento.



public event MyEventHandler PropertyChanged;
 
public delegate void MyEventHandler(Object sender
        , MyEventArgs e);
    public class MyEventArgs
        : System.ComponentModel.PropertyChangedEventArgs {
        public object Value { get; private set; }
        public MyEventArgs(string propertyName, object value)
            : base(propertyName) {
            Value = value;
        }
    }

Las otras formas de declarar eventos son para casos mas complejos como "eventos read only" y por lo general no se usan.

viernes, 7 de junio de 2013

Ejecutar programas desde .Net Framework

La funcionalidad para ejecutar un programa desde .Net Framework se encuentra en el espacio de nombres System.Diagnostics y es a través de las clases Process y ProcessStartInfo.
La clase Process representa un programa en ejecución y ProcessStartInfo los parámetros con que se ejecuta el proceso entre otros: el nombre del programa, si se redirecciona la entrada y salida estándar, si se va a crear una ventana para el programa, el directorio de trabajo etc.
La forma en que se crea un proceso es usar el método  Start de la clase Process, ya sea el miembro estático con alguna de sus sobrecargas, para crear un nuevo objeto, o el miembro de instancia para usar un objeto construido previamente.
Las diferente sobrecargas nos sirven para ejecutar un programa indicando sus opciones directamente o usando un ProcessStartInfo para indicarlas, esta opción es la que nos permite mas flexibilidad.
En particular la opción  UseShellExecute es ideal para programas de linea de comandos.

A continuación el ejemplo:


using System;
using System.Diagnostics;
 
public class Class1
{
    public void StarP() {
        ProcessStartInfo stInfo = new ProcessStartInfo("prog.exe");
        stInfo.UseShellExecute = false;
        Process proc = Process.Start(stInfo);
        proc.WaitForExit();
    }
}

jueves, 6 de junio de 2013

Gestionar excepciones de manera global en Asp.Net

Asp.Net tiene una forma de pescar cualquier excepción que ocurra en el sitio de forma centralizada.
En efecto lo único que tenemos que hacer es implementar el metodo Application_Error del archivo Global.asax en un sitio web y este se ejecutara cada vez que ocurra una excepción no controlada en la aplicación.
La excepción que ocurrió esta disponible accesando la función Server.GetLastError().
Por ejemplo podemos capturar la excepción y reportarla usando nlog, mandarla por email, etc.

lunes, 3 de junio de 2013

Agregar Web Services en Visual Studio 2008 en adelante

En las versiones mas recientes de Visual Studio no se tiene la opción directa para añadir Web Services al proyecto, lo que se tiene es la opción de agregar referencias de servicios, estos servicios son los creados con WCF y aunque se puede usar un Web Service antiguo con WCF en ocasiones podemos necesitar un Web Service sin usar WPF por ejemplo si no queremos incluir la referencia a esos componentes en el proyecto.
En estos casos podemos incluir el Web Service siguiendo estos pasos.
Se selecciona agregar referencia de servicio como si fuéramos a agregar un servicio WCF.
En esta ventana seleccionamos el botón "Avanzadas..."



En la ventana que aparece seleccionamos "Agregar referencia web..."


Y finalmente nos aparece la pantalla para agregar un Web Service "clásico"