Buscar este blog

miércoles, 24 de julio de 2013

Visual Studio no depura

A veces cuando queremos depurar un programa en Visual Studio 2010 el entorno no inicia la depuración, el proyecto se compila sin problemas pero el programa no inicia.
Esto puede deberse al que el proceso vshost del programa "se colgó", para solucionar esto hay que abrir el administrador de tareas y matar el proceso, después de esto se debe iniciar la depuración la próxima vez.

domingo, 30 de junio de 2013

Usando Invoke con una expresión Lambda

A veces queremos usar el método Invoke de un control o form de Windows.Forms sin llenarnos de delegados, simplemente escribir el código en el lugar donde se usa, para esto podemos debemos "castear" la expresión a un objeto Action, muy simple:



Invoke((Action)(() => {
    Close();
}));

viernes, 21 de junio de 2013

Menus en click derecho de Gkt sharp

Pues resulta que en gtk los menús no aparecen cuando se da click derecho, afortunadamente Dave Glick ha publicado esta clase para solucionarlo.
Les incluyo el código ligeramente modificado si no quieren navegar a otra pagina:


using System;
using Gdk;
using GLib;
using Gtk;
 
namespace Somedave {
    public class ContextMenuEventArgs: EventArgs {
        private Widget widget;
        public Widget Widget { get { return widget; } }
 
        private bool rightClick;
        public bool RightClick { get { return rightClick; } }
 
        public ContextMenuEventArgs(Widget widget, bool rightClick) {
            this.widget = widget;
            this.rightClick = rightClick;
        }
    }
 
    public class ContextMenuHelper {
        public event EventHandler<ContextMenuEventArgs> ContextMenu;
 
        public ContextMenuHelper() { }
 
        public ContextMenuHelper(Widget widget) {
            AttachToWidget(widget);
        }
 
        public ContextMenuHelper(Widget widget, EventHandler<ContextMenuEventArgs> handler) {
            AttachToWidget(widget);
            ContextMenu += handler;
        }
 
        public void AttachToWidget(Widget widget) {
            widget.PopupMenu += Widget_PopupMenu;
            widget.ButtonPressEvent += Widget_ButtonPressEvent;
        }
 
        public void DetachFromWidget(Widget widget) {
            widget.PopupMenu -= Widget_PopupMenu;
            widget.ButtonPressEvent -= Widget_ButtonPressEvent;
        }
 
        [GLib.ConnectBefore]
        private void Widget_PopupMenu(object o, PopupMenuArgs args) {
            RaiseContextMenuEvent(args, (Widget)o, false);
        }
 
        [GLib.ConnectBefore]
        private void Widget_ButtonPressEvent(object o, ButtonPressEventArgs args) {
            if(args.Event.Button == 3 && args.Event.Type == EventType.ButtonPress) {
                RaiseContextMenuEvent(args, (Widget)o, true);
            }
        }
 
        private bool propagating = false;   //Prevent reentry
 
        private void RaiseContextMenuEvent(SignalArgs signalArgs, Widget widget, bool rightClick) {
            if(!propagating) {
                //Propagate the event
                Event evnt = Gtk.Global.CurrentEvent;
                propagating = true;
                Gtk.Global.PropagateEvent(widget, evnt);
                propagating = false;
                signalArgs.RetVal = true;     //The widget already processed the event in the propagation
 
                //Raise the context menu event
                ContextMenuEventArgs args = new ContextMenuEventArgs(widget, rightClick);
                if(ContextMenu != null) {
                    ContextMenu.Invoke(this, args);
                }
            }
        }
    }
}

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!