jueves, 14 de mayo de 2009

Cantidad de Visitas al Articulo:

Office Communicator 2007 - Alertas

clip_image002Debido a un proyecto en el que estoy involucrado, tuve que investigar como integrar a nuestro sistema, el uso del Office Communicator 2007 (OC) para el envío de alertas a los usuarios.

Poco sabía del producto, y bastante me costó encontrar información de utilidad para poder hacerlo.

Aquí expongo algunos tips que creo de utilidad para poder realizar ésta tarea, con ejemplo concretos.

Espero les sirva, para no tener que navegar. tanto por internet :-).

Contexto

Office Communicator 2007 es un sistema de mensajería desarrollado por Microsoft, que permite establecer comunicaciones entre usuarios de un dominio, ya sea a través de mensajes instantáneos o voz, y compartir información.

Tiene varias características de ayuda al negocio, que pueden revisar en la descripción del producto en el sitio oficial.

El Desafío

Nuestro sistema es web. Es un manejador documental que permite un flujo manual de documentos, con bandejas de entradas y salidas de documentos.

El pedido concreto era que un usuario al que se le enviara un documento en esa bandeja de entrada, recibiera un alerta en su Communicator corporativo, con un texto del tipo: “Ud. ha recibido un el documento DDD de parte del usuario UUU. Ingrese a URL …”, a través de un IM (Instant Message)

(Esto es posible en esta compañía, porque el usuario en el momento en que se loguea en su máquina, automáticamente abre el OC).

Dado que el IM es una comunicación de máquina a máquina, y se hace a través del OC, que es una aplicación local, no es factible utilizar una especie de repositorio o cola en un servidor.

La Solución

En primer lugar, para poder trabajar desde C#, lenguaje utilizado en nuestro caso, debimos descargar la API del producto para poder instanciarlo desde programa.

Luego, debimos comprender que se trata de una aplicación stand alone, por lo que no es un sistema de mensajería como el mail, donde el encargado de “rutear” el mensaje es el servidor.

Para poder enviar un mensaje se debe instanciar el OC, a través de la instrucción:

using CommunicatorAPI;

private Messenger _communicator;
private IMessengerAdvanced _communicatorAdvanced;

if (_communicator == null)
{
_communicator = new Messenger();
_communicatorAdvanced = _communicator as IMessengerAdvanced;

_communicator.OnSignin += new DMessengerEvents_OnSigninEventHandler(communicator_OnSignin);
_communicator.OnSignout += new DMessengerEvents_OnSignoutEventHandler(communicator_OnSignout);
_communicator.OnIMWindowCreated += new DMessengerEvents_OnIMWindowCreatedEventHandler(communicator_OnIMWindowCreated);
_communicator.OnIMWindowDestroyed += new DMessengerEvents_OnIMWindowDestroyedEventHandler(communicator_OnIMWindowDestroyed);
_communicator.OnAppShutdown += new DMessengerEvents_OnAppShutdownEventHandler(communicator_OnAppShutdown);
}

luego hacer el LogIn:

_communicator.Signin(0, _userIM, _pswIM);

donde el _userIM es un usaurio que se conectará al sistema, y que debe ser un usuario válido, sino fallará el proceso. Esto significa que se debe tener un usuario genérico de conexión por cada servidor redundante de nuestro sistema, desde donde se desea enviar alarmas.

Una vez logueado, para enviar un mensaje IM, nos debemos “colgar” del evento de apertura de una ventana (DMessengerEvents_OnIMWindowCreatedEventHandler) de la forma:

void communicator_OnIMWindowCreated(object pIMWindow)
{
try
{
IMessengerConversationWndAdvanced imWindow = (IMessengerConversationWndAdvanced)pIMWindow;

if (((IMessengerConversationWndAdvanced)pIMWindow).HWND == windowHandle)
{
// outgoing
if (!String.IsNullOrEmpty(_messageIM))
imWindow.SendText(_messageIM);

imWindow.Close();
windowHandle = 0;
_messageIM = null;
}
else
{
// incoming
windowHandle = imWindow.HWND;
}
}
catch (COMException comException)
{
log.Error(communicator_OnIMWindowCreated [comException].", comException);
}
catch (Exception exception)
{
log.Error("communicator_OnIMWindowCreated [exception].", exception);
}
}

Donde el envío se hace exactamente en la línea:

if (!String.IsNullOrEmpty(_messageIM))
imWindow.SendText(_messageIM);

Siendo _messageIM una variable global antes completada.

Pero para enviar el mensaje se debe abrir la ventana. Para esto podemos usar:

public void SendIM(string userIM, string msgIM)
{
try
{
if (msgIM != null) _messageIM = msgIM;
// Find the Contact using the SipUri
IMessengerContact contact = null;
if (userIM != null)
contact = (IMessengerContact)_communicator.GetContact(userIM, _communicator.MyServiceId);

// Use IMessenger.InstantMessage to send an IM
if (contact != null)
{
IMessengerWindow window = (IMessengerWindow)_communicator.InstantMessage(contact);
windowHandle = window.HWND; // Capture window handle
System.Threading.Thread.Sleep(_timeToSleepBetweebnMsgIM);
log.Debug("OCSender.SendAllIM - Contacto encontrado " + userIM +
", para enviar mensaje: " + msgIM);
}
else
{
log.Debug("OCSender.SendAllIM - No encontro el contacto " + userIM +
", para enviar mensaje: " + msgIM);
}
}
catch (Exception e)
{
log.Error("SendIM [exception].", e);
}
}

Donde userIM es un usuario corporativo, definido por su mail o userid, y msgIM el mensaje propiamente dicho.

Notarán que existe un Sleep, y esto se debe a que se debe dar el tiempo suficiente a la apertura de la ventana y la ejecución del correspondiente código en el evento de apertura, para evitar saltear mensajes.

Ahora bien, si existe la posibilidad de concurrencia en la emisión de alertas, deberíamos manejar una cola de mensajes, y tener una rutina que agregue mensajes a la cola y otra rutina que envíe en algún momento todos los mensajes encolados. Para acceder a dicha cola se podría acceder bloqueándola, para evitar problemas, de la forma:

lock (_colaMsg)
{
_colaMsg.Add(new MensajeIM(toUserIM, messageIM));
}

Donde MensajeIM es un clase que tiene dos propiedades para efectuar luego los envíos.

Espero les sirva, y de necesitar algún soporte, no duden en contactarme. Les puedo enviar una clase que hace todo esto.

So far, So good!

Leer más...
 
Este Weblog, InforMateando..., está licenciado bajo Licencia Creative Common - por Gustavo Suhit