lunes, 19 de julio de 2010

Monitorizando colas de Exchange 2007


Get-Queue -server nombre_servidor_exchange2007

es el comando PowerShell que muestra una instantánea del número de mensajes de las colas del servidor de correo Exchange 2007.

Una buena mejora en la visualización de resultados de este comando sería que éstos aparecieran en una ventanita de Windows y se actualizara con cierta frecuencia:

Para conseguirlo, escribiremos una aplicación en C# que internamente ejecute nuestro comando en PowerShell y envíe su salida a un Listview con los resultados, todo en una ventanita.

Para que esto funcione, tanto en el desarrollo de la aplicación como en la ejecución posterior del .exe, es necesario utilizar un usuario que tenga permisos para visualizar las colas, por ej. el administrador de dominio.





Requisitos de software en el host de desarrollo:

- SharpDevelop
- Powershell 2
- Consola de administración de Exchange 2007
- .NET Framework 3.5

Instalado todo esto, abrimos SharpDevelop con el usuario que tenga permisos para ver las colas de Exchange 2007 y creamos en un proyecto nuevo una nueva aplicación de Windows que se llame "colas_correo", de esta forma:

Creada la aplicación, tendremos una ventana vacía que es el formulario por defecto "MainForm". A la derecha de la vista de diseño del formulario tenemos la columna de propiedades del elemento que tengamos seleccionado. Seleccionamos la ventana del formulario y en la lista de propiedades buscamos la propiedad "Text", y le ponemos el nombre que queramos para que aparezca como título de la ventana, por ej. "Colas Exchange".

Dentro del formulario creamos una etiqueta cuya propiedad (Name) sea "leyenda_form". La propiedad Text de esta etiqueta la modificaremos dinámicamente para visualizar la fecha/hora de la última consulta a las colas.

Debajo de la etiqueta creamos un ListView con dos columnas, seleccionamos el ListView creado, clicamos en la flechita que está cerca de la esquina superior derecha del ListView, clicamos en "Editar columnas" y agregamos un miembro 0 (columna izquierda) donde su propiedad (Name) debe tener el valor: cola_form, y la propiedad Text debe tener el valor: Cola. Después agregamos otro miembro 1 (columna derecha) donde su propiedad (Name) debe tener el valor: mensajes_form y la propiedad Text debe tener el valor: Mensaje.

Aceptamos ventanas y pasamos a picar código. Clicamos en la pestaña "Fuente" de abajo y podremos editar el código de este formulario que es el que utilizaremos. El archivo que contendrá este código es MainForm.cs y estará ubicado en la carpeta del proyecto.

También tienes disponible el código de MainForm.cs en este enlace.

En el comienzo del archivo MainForm.cs aparece por defecto una lista de directivas using que tenemos que completar dejándolas así:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
using System.Text;

Para evitar errores en la compilación relacionados con la falta de referencias, seguramente sea necesario agregar las referencias correspondientes para alguno de estos using. Lo puedes hacer desde el menú Proyecto, Agregar Referencia, pestaña GAC, buscar la referencia correspondiente, seleccionarla y OK.

Después de la lista de los using, hay un namespace cuyo nombre da igual para nuestro propósito. Dentro de tal, tendremos un public partial class MainForm: Form que es la clase de nuestro formulario y dentro de ella hay métodos (funciones), entre ellos, el punto de entrada es el método public MainForm() que se encarga de iniciar el formulario.

Dentro de public MainForm(), lo primero es el método InitializeComponent() que se encarga de inicializar el formulario con las propiedades por defecto, y justo después crearemos un Timer para que nuestra aplicación saque datos cada minuto:

Timer timer1 = new Timer();
timer1.Interval = 60000; // un minuto
timer1.Enabled = true;
timer1.Tick += new System.EventHandler (OnTimerEvent);

Además, necesitamos un método
OnTimerEvent()
que tiene que ir al mismo nivel que public MainForm(), así:

public void OnTimerEvent(object source, EventArgs e)
{
saca_datos();
leyenda_form.Text = "Última actualización: " + DateTime.Now.ToLongTimeString();
}

leyenda_form
es el nombre de una etiqueta dentro del formulario que indica la última fecha/hora que se hizo la consulta a las colas (no olvides tenerla ubicada visualmente en el formulario con la propiedad (Name) adecuada).

saca_datos()
es el método que hará la invocación a PowerShell y sacará los datos de la cola. También debe ir al mismo nivel que public MainForm().

Importante:
el método saca_datos() debes editarlo para definir la variable "servidor" con el nombre DNS de tu servidor Exchange 2007.

El código del método saca_datos() es el siguiente:

private void saca_datos()
{
lista_form.Items.Clear();
// edita la siguiente línea con el nombre DNS de tu servidor de correo
string servidor = "el_nombre_de_tu_servidor_exchange";

RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
PSSnapInException snapInException = null;
PSSnapInInfo info = rsConfig.AddPSSnapIn
("Microsoft.Exchange.Management.PowerShell.Admin", out snapInException);
Runspace myRunSpace = RunspaceFactory.CreateRunspace(rsConfig);
myRunSpace.Open();
Pipeline pipeLine = myRunSpace.CreatePipeline();

// comando powershell
Command myCommand = new Command("Get-Queue");

//parámetros powershell
CommandParameter param_server = new CommandParameter("server", servidor);
myCommand.Parameters.Add(param_server);

//mete en la tubería de ejecución
pipeLine.Commands.Add(myCommand);

//ejecución
Collection commandResults = pipeLine.Invoke();

//resultados
string cola = "";
string mensajes = "";

foreach (PSObject cmdlet in commandResults)
{
cola = cmdlet.Properties["NextHopDomain"].Value.ToString();
mensajes = cmdlet.Properties["MessageCount"].Value.ToString();

//saca datos en lista
ListViewItem i = new ListViewItem();
i.Text = cola;
i.SubItems.Add(mensajes);
lista_form.Items.Add(i);
}
}


Y listo, con esto sólo queda darle a F5 para compilar y ejecutar la solución.

Si todo es correcto, el ejecutable colas_correo.exe lo encontrarás en la carpeta debug o release dentro de la carpeta bin del proyecto, el cual podrás utilizar directamente.