´

C# – Recibir notificaciones cuando hayan cambios de sesión parte 1

 

Esta es una copia cruzada de mi blog original.

Puedes leer el articulo original con código coloreado y demás utilidades en 

C# – Recibir notificaciones cuando hayan cambios de sesión parte 1

--------------

Artículos de este tema:

*Realmente son 6 articulos si contamos los mini post a los que se hace referencia

A veces necesitamos que nuestro software audite ciertos eventos generados por el equipo, como por ejemplo cuando se abren o cierran sesiones. Esto es importante por ejemplo para disparar procesos pesados cuando el computador no este en uso o para realizar procesos de auditoria.

Como es de suponerse el .Net Framework no trae nada que nos apoye en esa tarea ya que esta profundamente relacionada con el sistema operativo y ya que el CLR es multiplataforma este tipo de cosas no vienen soportadas. Se debe hacer uso de la Api de Windows.

 

En este artículo crearé una librería sencilla que permite ser notificado cuando suceden estos eventos bien sea en la sesión actual o a través de las diferentes sesiones iniciadas en el sistema.

 

NUESTRO KIT DE HERRAMIENTAS

Las cosas que necesitamos de la Api de Windows para realizar esta labor se describen a continuación

 

Funciones

Constantes para llamar a WTSRegisterSessionNotification

  • NOTIFY_FOR_THIS_SESSION : Notifica eventos de la sesión actual
  • NOTIFY_FOR_ALL_SESSIONS : Notifica eventos de todas las sesiones del sistema

Constantes relacionadas con las notificaciones

  • WM_WTSSESSION_CHANGE : Mensaje generado cuando suceden los eventos de cambios en la sesión
  • Parámetros:
    • WTS_CONSOLE_CONNECT: Una sesión se ha conectado por terminal de consola.
    • WTS_CONSOLE_DISCONNECT: Una sesión se ha desconectado por terminal de consola.
    • WTS_REMOTE_CONNECT: Una sesión se ha conectado por una terminal remota.
    • WTS_REMOTE_DISCONNECT: Una sesión de terminal remota se ha desconectado.
    • WTS_SESSION_LOGON: Un usuario se ha logueado en la sesión.
    • WTS_SESSION_LOGOFF: Un usuario se ha deslogueado de la sesión
    • WTS_SESSION_LOCK: Una sesión se ha bloqueado.
    • WTS_SESSION_UNLOCK: Una sesión se ha desbloqueado.
    • WTS_SESSION_REMOTE_CONTROL: Una sesión ha cambiado su estado de control remoto. Par determinar el estado se debe hacer uso de GetSystemMetrics y revisar la métrica SM_REMOTECONTROL.

LETS CODE!

Preparando las funcionalidades de la Win32 API

Creamos una clase para centralizar los llamados a la API, allí con ayuda de DllImport importamos las funciones que requerimos y definimos todas las constantes necesarias, de preferencia agrupadas en enums:

Enums necesarias

[csharp]
/// Notificaciones a recibir
public enum NotifyType
{
    /// Notificacion para la sesion actual
    NOTIFY_FOR_THIS_SESSION = 0,
    /// Notificacion para todas las sesiones del sistema
    NOTIFY_FOR_ALL_SESSIONS = 1
}

/// Tipo de notificacion recibida
public enum SessionNotificationMsg
{
    /// Una sesión se ha conectado por terminal de consola.
    WTS_CONSOLE_CONNECT = 0x1,
    /// Una sesión se ha desconectado por terminal de consola.
    WTS_CONSOLE_DISCONNECT = 0x2,
    /// Una sesión se ha conectado por una terminal remota.
    WTS_REMOTE_CONNECT = 0x3,
    /// Una sesión de terminal remota se ha desconectado.
    WTS_REMOTE_DISCONNECT = 0x4,
    /// Un usuario se ha logueado en la sesión.
    WTS_SESSION_LOGON = 0x5,
    /// Un usuario se ha deslogueado de la sesión.
    WTS_SESSION_LOGOFF = 0x6,
    /// Una sesión se ha bloqueado.
    WTS_SESSION_LOCK = 0x7,
    /// Una sesión se ha desbloqueado.
    WTS_SESSION_UNLOCK = 0x8,
    /// Una sesión ha cambiado su estado de control remoto. Par determinar el estado se debe hacer uso de GetSystemMetrics y revisar la métrica SM_REMOTECONTROL.
    WTS_SESSION_REMOTE_CONTROL = 0x9
}
[/csharp]

Ahora la clase para manejar la W32API

[csharp]
using System;
using System.Runtime.InteropServices;

public static class W32HandleSessionChanges
{
    /// 
    /// Registra una ventana para recibir notificaciones de cambios en las sesiones
    /// 
    /// Manejador de la ventana
    /// Modificadores 
    /// NOTIFY_FOR_THIS_SESSION, NOTIFY_FOR_ALL_SESSIONS
    /// 
    /// 
    [DllImport("wtsapi32.dll", SetLastError = true)]
    public static extern bool WTSRegisterSessionNotification(IntPtr hWnd, NotifyType dwFlags);

    /// 
    /// Des Registra una ventana que recibe notificaciones de cambios en las sesiones
    /// 
    /// Manejador de la ventana
    /// 
    [DllImport("wtsapi32.dll", SetLastError = true)]
    public static extern bool WTSUnRegisterSessionNotification(IntPtr hWnd);

    /// Mensaje recibido cuando hay cambios en las sesiones
    public const int WM_WTSSESSION_CHANGE = 0x2b1;

}
[/csharp]

Para usarla basta con hacer uso del método W32HandleSessionChanges.WTSRegisterSessionNotification, el parámetro hWnd es el manejador de la ventana donde queremos recibir la notificaciones, esto nos permite registrar la ventana actual para recibir este tipo de mensajes, asi que una vez hecho esto se deben interceptar los mensajes para hacer lo que necesitemos. Una vez se valla a cerrar nuestro programa siempre es coveniente llamar a WTSUnRegisterSessionNotification

La librería que he creado se puede usar en diferentes tipos de aplicación para  comenzar a recibir notificaciones, en próximos artículos les mostrare como utilizarla  en Windows Forms y en WPF.

 

Leave a Comment

(required) 

(required) 

(optional)
 

(required) 

If you can't read this number refresh your screen
Enter the numbers above: